mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-13 12:55:06 +00:00
Compare commits
167 Commits
Alpha_1.4d
...
Alpha_1.4d
Author | SHA1 | Date | |
---|---|---|---|
c7f578f297 | |||
19c030281f | |||
ca9fe1b89a | |||
9fd6a695f6 | |||
c07b0ff35b | |||
6796fca2b6 | |||
5657cce3db | |||
05ac256cc3 | |||
49977c5410 | |||
ca40bb678c | |||
2068cc9cdf | |||
ea4617cedd | |||
1a5544f68c | |||
0128a7aeb2 | |||
fd954ce708 | |||
d63a82de0a | |||
92143d523c | |||
1818e64c8e | |||
7e1095e28d | |||
f1519e6d13 | |||
3b9a9bcd5d | |||
263bff01c8 | |||
987d647b76 | |||
522b75645c | |||
9eed0a579c | |||
064976d32b | |||
2abb577178 | |||
127855c220 | |||
93c7a3c170 | |||
31903a764a | |||
79bc1d6c85 | |||
cc7f12739d | |||
32dae93ef9 | |||
8fd6582e74 | |||
a5369b3570 | |||
abbd33210a | |||
6b6222c09c | |||
a8c997d88a | |||
6993718a83 | |||
86afecec89 | |||
29d1fd1fc8 | |||
af4eb2ab1e | |||
f7baf46a54 | |||
75c0d8324c | |||
da4334f06b | |||
413bd3c0df | |||
1a0428654b | |||
2803a38fd1 | |||
95a5ca7889 | |||
240f14c425 | |||
cb9b6ab1d1 | |||
8a87280566 | |||
4d97827d44 | |||
f8f1e0e9df | |||
bf596ebf05 | |||
90777014b6 | |||
4a78ffd2dd | |||
7c361a52d2 | |||
13fc0df92c | |||
d5012f6fcf | |||
4569a73f3d | |||
66acb5cdd7 | |||
8601405a88 | |||
ae06681b60 | |||
01ffb14e39 | |||
ce989876af | |||
f8d6ebabf3 | |||
094b600a0c | |||
82cfe6ea9c | |||
4fba6d7c86 | |||
f72d7284b9 | |||
8f0527832f | |||
f66944368d | |||
7ab3c57b00 | |||
673b867ee8 | |||
2424c8a76c | |||
92eb5cb0b8 | |||
fd46c71120 | |||
6a4259bf24 | |||
9a65279c6a | |||
09a01be709 | |||
57d1847c50 | |||
6e8e2a79dd | |||
d8f9def7f4 | |||
8cb9dd9a14 | |||
c4c374e3fa | |||
d57e37896d | |||
022a978ffb | |||
00b282d40c | |||
8a768cea33 | |||
289bc56b4b | |||
6f64af3066 | |||
72c09045d5 | |||
5e55c3a8f0 | |||
afaa2cf722 | |||
50cfeaa393 | |||
dda8b03349 | |||
56e848488a | |||
7e4f862634 | |||
577a7a1c3d | |||
78f8d0280d | |||
0680b98380 | |||
cbe0fe5e46 | |||
7eed92e8fb | |||
f772391866 | |||
8c4faa8622 | |||
b6f7ee20fc | |||
0fce83c671 | |||
8080643cc9 | |||
5bf2174cad | |||
34ae760def | |||
a5b85c549a | |||
b9f1812f61 | |||
350cee3d41 | |||
144a871c07 | |||
69492474e4 | |||
4299ebebcc | |||
119b429ab8 | |||
8f1eb41ca5 | |||
ca92d2a0d3 | |||
db82f76c11 | |||
3f5b129cf5 | |||
f6aac8728b | |||
809fc44813 | |||
64f1ff066d | |||
a5a3f4801a | |||
23d1532ff9 | |||
ecbbcc2e8e | |||
7abf52e615 | |||
9e01e2ef49 | |||
df81b365e5 | |||
db8ac0b9cb | |||
ee4f416d93 | |||
8feea721e3 | |||
8e7077ff4b | |||
4f4a6e7446 | |||
1fc066fc37 | |||
b565844062 | |||
be948f99cc | |||
5cb428e5cc | |||
d2f4a14d66 | |||
516bb37a50 | |||
580ade9092 | |||
8f7dfe0b71 | |||
5310ba3ae6 | |||
ef97efcd96 | |||
30c3718ea8 | |||
5437567e95 | |||
e3e97a4205 | |||
fec387d2ec | |||
481e2b08ee | |||
15de0eece7 | |||
2f8267aa1e | |||
f2b573c32f | |||
34946faf94 | |||
3b47513439 | |||
7d9a98ec6b | |||
92facc94b9 | |||
d3327f450c | |||
570cab9c66 | |||
582ba100b0 | |||
4c0daa462d | |||
2e6366868d | |||
245e9b4f18 | |||
68e73d4e3a | |||
684617d370 | |||
a879104a6f |
@ -10,7 +10,7 @@ before_script:
|
||||
- mkdir plugins
|
||||
- wget -O plugins/DevTools.phar https://github.com/PocketMine/DevTools/releases/download/v1.9.0/DevTools_v1.9.0.phar
|
||||
- pecl install channel://pecl.php.net/pthreads-2.0.10
|
||||
- pecl install channel://pecl.php.net/weakref-0.2.4
|
||||
- pecl install channel://pecl.php.net/weakref-0.2.6
|
||||
- echo | pecl install channel://pecl.php.net/yaml-1.1.1
|
||||
|
||||
script:
|
||||
@ -18,4 +18,4 @@ script:
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
#webhooks: http://n.tkte.ch/h/214/wsNvmG43-ncxUVRrFPwSM-r0
|
||||
#webhooks: http://n.tkte.ch/h/214/wsNvmG43-ncxUVRrFPwSM-r0
|
||||
|
@ -137,7 +137,7 @@ class CrashDump{
|
||||
$error = $lastExceptionError;
|
||||
}else{
|
||||
$error = (array) error_get_last();
|
||||
$error["trace"] = getTrace(4);
|
||||
$error["trace"] = @getTrace(4);
|
||||
$errorConversion = [
|
||||
E_ERROR => "E_ERROR",
|
||||
E_WARNING => "E_WARNING",
|
||||
|
@ -24,9 +24,9 @@ namespace pocketmine;
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\entity\Arrow;
|
||||
use pocketmine\entity\DroppedItem;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\Human;
|
||||
use pocketmine\entity\Item as DroppedItem;
|
||||
use pocketmine\entity\Living;
|
||||
use pocketmine\entity\Projectile;
|
||||
use pocketmine\event\block\SignChangeEvent;
|
||||
@ -36,6 +36,7 @@ use pocketmine\event\entity\EntityRegainHealthEvent;
|
||||
use pocketmine\event\entity\EntityShootBowEvent;
|
||||
use pocketmine\event\entity\ProjectileLaunchEvent;
|
||||
use pocketmine\event\inventory\InventoryCloseEvent;
|
||||
use pocketmine\event\inventory\InventoryPickupArrowEvent;
|
||||
use pocketmine\event\inventory\InventoryPickupItemEvent;
|
||||
use pocketmine\event\player\PlayerAchievementAwardedEvent;
|
||||
use pocketmine\event\player\PlayerAnimationEvent;
|
||||
@ -46,6 +47,7 @@ use pocketmine\event\player\PlayerCommandPreprocessEvent;
|
||||
use pocketmine\event\player\PlayerDeathEvent;
|
||||
use pocketmine\event\player\PlayerDropItemEvent;
|
||||
use pocketmine\event\player\PlayerGameModeChangeEvent;
|
||||
use pocketmine\event\player\PlayerInteractEvent;
|
||||
use pocketmine\event\player\PlayerItemConsumeEvent;
|
||||
use pocketmine\event\player\PlayerJoinEvent;
|
||||
use pocketmine\event\player\PlayerKickEvent;
|
||||
@ -72,6 +74,7 @@ use pocketmine\level\format\LevelProvider;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\Location;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\metadata\MetadataValue;
|
||||
use pocketmine\nbt\NBT;
|
||||
@ -91,6 +94,7 @@ use pocketmine\network\protocol\Info as ProtocolInfo;
|
||||
use pocketmine\network\protocol\LoginStatusPacket;
|
||||
use pocketmine\network\protocol\MessagePacket;
|
||||
use pocketmine\network\protocol\MovePlayerPacket;
|
||||
use pocketmine\network\protocol\SetDifficultyPacket;
|
||||
use pocketmine\network\protocol\SetHealthPacket;
|
||||
use pocketmine\network\protocol\SetSpawnPositionPacket;
|
||||
use pocketmine\network\protocol\SetTimePacket;
|
||||
@ -138,7 +142,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
protected $sendIndex = 0;
|
||||
|
||||
public $blocked = true;
|
||||
public $blocked = false;
|
||||
public $achievements = [];
|
||||
public $lastCorrect;
|
||||
/** @var SimpleTransactionGroup */
|
||||
@ -242,7 +246,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
* @param Player $player
|
||||
*/
|
||||
public function spawnTo(Player $player){
|
||||
if($this->spawned === true and $this->dead !== true and $player->getLevel() === $this->level and $player->canSee($this)){
|
||||
if($this->spawned === true and $this->dead !== true and $this !== $player and $player->getLevel() === $this->level and $player->canSee($this)){
|
||||
parent::spawnTo($player);
|
||||
}
|
||||
}
|
||||
@ -420,11 +424,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->port = $port;
|
||||
$this->clientID = $clientID;
|
||||
$this->chunksPerTick = (int) $this->server->getProperty("chunk-sending.per-tick", 4);
|
||||
$this->spawnPosition = $this->server->getDefaultLevel()->getSafeSpawn();
|
||||
$this->spawnPosition = null;
|
||||
$this->gamemode = $this->server->getGamemode();
|
||||
$this->setLevel($this->server->getDefaultLevel(), true);
|
||||
$this->viewDistance = $this->server->getViewDistance();
|
||||
$this->newPosition = new Vector3(0, 0, 0);
|
||||
$this->boundingBox = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -528,9 +533,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
$this->level->freeChunk($x, $z, $this);
|
||||
unset($this->usedChunks[$index]);
|
||||
}
|
||||
$this->level->freeChunk($x, $z, $this);
|
||||
unset($this->loadQueue[$index]);
|
||||
}
|
||||
|
||||
@ -581,7 +586,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
return;
|
||||
}
|
||||
|
||||
$pk = new FullChunkDataPacket;
|
||||
$pk = new FullChunkDataPacket();
|
||||
$pk->chunkX = $x;
|
||||
$pk->chunkZ = $z;
|
||||
$pk->data = $payload;
|
||||
@ -594,7 +599,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
protected function sendNextChunk(){
|
||||
if($this->connected === false){
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
@ -622,13 +627,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->level->requestChunk($X, $Z, $this, LevelProvider::ORDER_ZXY);
|
||||
}
|
||||
|
||||
|
||||
if(count($this->usedChunks) < 16 and $this->spawned === true){
|
||||
$this->blocked = true;
|
||||
}elseif($this->spawned === true){
|
||||
$this->blocked = false; //TODO: reason of block to revert
|
||||
}
|
||||
|
||||
if(count($this->usedChunks) >= 56 and $this->spawned === false){
|
||||
$spawned = 0;
|
||||
foreach($this->usedChunks as $d){
|
||||
@ -638,20 +636,17 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
|
||||
if($spawned < 56){
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->spawned = true;
|
||||
|
||||
$this->blocked = false;
|
||||
|
||||
$pk = new SetTimePacket;
|
||||
$pk = new SetTimePacket();
|
||||
$pk->time = $this->level->getTime();
|
||||
$pk->started = $this->level->stopTime == false;
|
||||
$this->dataPacket($pk);
|
||||
|
||||
$pos = new Position($this->x, $this->y, $this->z, $this->level);
|
||||
$pos = $this->level->getSafeSpawn($pos);
|
||||
$pos = $this->level->getSafeSpawn($this);
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerRespawnEvent($this, $pos));
|
||||
|
||||
@ -722,13 +717,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$X = null;
|
||||
$Z = null;
|
||||
Level::getXZ($index, $X, $Z);
|
||||
foreach($this->level->getChunkEntities($X, $Z) as $entity){
|
||||
if($entity !== $this){
|
||||
$entity->despawnFrom($this);
|
||||
}
|
||||
}
|
||||
|
||||
unset($this->usedChunks[$index]);
|
||||
$this->unloadChunk($X, $Z);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -794,10 +783,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
* @return boolean
|
||||
*/
|
||||
public function sleepOn(Vector3 $pos){
|
||||
foreach($this->level->getPlayers() as $p){
|
||||
if($p->sleeping instanceof Vector3){
|
||||
if($pos->distance($p->sleeping) <= 0.1){
|
||||
return false;
|
||||
foreach($this->level->getNearbyEntities($this->boundingBox->grow(2, 1, 2), $this) as $p){
|
||||
if($p instanceof Player){
|
||||
if($p->sleeping instanceof Vector3){
|
||||
if($pos->distance($p->sleeping) <= 0.1){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -807,7 +798,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->sleeping = $pos;
|
||||
$this->sleeping = clone $pos;
|
||||
$this->teleport(new Position($pos->x + 0.5, $pos->y + 1, $pos->z + 0.5, $this->level));
|
||||
|
||||
$this->sendMetadata($this->getViewers());
|
||||
@ -832,7 +823,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$level = $pos->getLevel();
|
||||
}
|
||||
$this->spawnPosition = new Position($pos->x, $pos->y, $pos->z, $level);
|
||||
$pk = new SetSpawnPositionPacket;
|
||||
$pk = new SetSpawnPositionPacket();
|
||||
$pk->x = (int) $this->spawnPosition->x;
|
||||
$pk->y = (int) $this->spawnPosition->y;
|
||||
$pk->z = (int) $this->spawnPosition->z;
|
||||
@ -861,7 +852,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
$time = $this->level->getTime() % Level::TIME_FULL;
|
||||
|
||||
if($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);{
|
||||
if($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE){
|
||||
foreach($this->level->getPlayers() as $p){
|
||||
if($p->sleeping === false){
|
||||
return;
|
||||
@ -945,7 +936,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
$spawnPosition = $this->getSpawn();
|
||||
|
||||
$pk = new StartGamePacket;
|
||||
$pk = new StartGamePacket();
|
||||
$pk->seed = $this->level->getSeed();
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y + $this->getEyeHeight();
|
||||
@ -1015,7 +1006,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$flags |= 0x20; //Show Nametags
|
||||
}
|
||||
|
||||
$pk = new AdventureSettingsPacket;
|
||||
$pk = new AdventureSettingsPacket();
|
||||
$pk->flags = $flags;
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
@ -1055,8 +1046,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
return;
|
||||
}
|
||||
|
||||
$oldPos = new Vector3($this->x, $this->y, $this->z);
|
||||
$distanceSquared = $oldPos->distanceSquared($this->newPosition);
|
||||
$distanceSquared = $this->newPosition->distanceSquared($this);
|
||||
|
||||
$revert = false;
|
||||
|
||||
@ -1067,6 +1057,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$chunk = $this->level->getChunk($this->newPosition->x >> 4, $this->newPosition->z >> 4);
|
||||
if(!($chunk instanceof FullChunk) or !$chunk->isGenerated()){
|
||||
$revert = true;
|
||||
$this->nextChunkOrderRun = 0;
|
||||
}else{
|
||||
if($this->chunk instanceof FullChunk){
|
||||
$this->chunk->removeEntity($this);
|
||||
}
|
||||
$this->chunk = $chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1124,7 +1120,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
if($to->distance($ev->getTo()) > 0.1){ //If plugins modify the destination
|
||||
$this->teleport($ev->getTo());
|
||||
}else{
|
||||
$pk = new MovePlayerPacket;
|
||||
$pk = new MovePlayerPacket();
|
||||
$pk->eid = $this->id;
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
@ -1139,10 +1135,10 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
|
||||
if($revert){
|
||||
$pk = new MovePlayerPacket;
|
||||
$pk = new MovePlayerPacket();
|
||||
$pk->eid = 0;
|
||||
$pk->x = $from->x;
|
||||
$pk->y = $from->y + $this->getEyeHeight();
|
||||
$pk->y = $from->y + $this->getEyeHeight() + 0.01;
|
||||
$pk->z = $from->z;
|
||||
$pk->bodyYaw = $from->yaw;
|
||||
$pk->pitch = $from->pitch;
|
||||
@ -1150,6 +1146,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$pk->teleport = true;
|
||||
$this->directDataPacket($pk);
|
||||
$this->forceMovement = new Vector3($from->x, $from->y, $from->z);
|
||||
$this->newPosition = null;
|
||||
}else{
|
||||
$this->forceMovement = null;
|
||||
if($this->nextChunkOrderRun > 20){
|
||||
@ -1199,20 +1196,20 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev = new InventoryPickupItemEvent($this->inventory, $item));
|
||||
$this->server->getPluginManager()->callEvent($ev = new InventoryPickupArrowEvent($this->inventory, $entity));
|
||||
if($ev->isCancelled()){
|
||||
continue;
|
||||
}
|
||||
|
||||
$pk = new TakeItemEntityPacket;
|
||||
$pk = new TakeItemEntityPacket();
|
||||
$pk->eid = 0;
|
||||
$pk->target = $entity->getID();
|
||||
$this->dataPacket($pk);
|
||||
$pk = new TakeItemEntityPacket;
|
||||
$pk = new TakeItemEntityPacket();
|
||||
$pk->eid = $this->getID();
|
||||
$pk->target = $entity->getID();
|
||||
Server::broadcastPacket($entity->getViewers(), $pk);
|
||||
$this->inventory->addItem(clone $item);
|
||||
$this->inventory->addItem(clone $item, $this);
|
||||
$entity->kill();
|
||||
}
|
||||
}elseif($entity instanceof DroppedItem){
|
||||
@ -1224,7 +1221,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev = new InventoryPickupItemEvent($this->inventory, $item));
|
||||
$this->server->getPluginManager()->callEvent($ev = new InventoryPickupItemEvent($this->inventory, $entity));
|
||||
if($ev->isCancelled()){
|
||||
continue;
|
||||
}
|
||||
@ -1238,15 +1235,15 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
break;
|
||||
}
|
||||
|
||||
$pk = new TakeItemEntityPacket;
|
||||
$pk = new TakeItemEntityPacket();
|
||||
$pk->eid = 0;
|
||||
$pk->target = $entity->getID();
|
||||
$this->dataPacket($pk);
|
||||
$pk = new TakeItemEntityPacket;
|
||||
$pk = new TakeItemEntityPacket();
|
||||
$pk->eid = $this->getID();
|
||||
$pk->target = $entity->getID();
|
||||
Server::broadcastPacket($entity->getViewers(), $pk);
|
||||
$this->inventory->addItem(clone $item);
|
||||
$this->inventory->addItem(clone $item, $this);
|
||||
$entity->kill();
|
||||
}
|
||||
}
|
||||
@ -1254,11 +1251,11 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
if($this->nextChunkOrderRun-- <= 0){
|
||||
if($this->nextChunkOrderRun-- <= 0 or $this->chunk === null){
|
||||
$this->orderChunks();
|
||||
}
|
||||
|
||||
if(count($this->loadQueue) > 0){
|
||||
if(count($this->loadQueue) > 0 or !$this->spawned){
|
||||
$this->sendNextChunk();
|
||||
}
|
||||
|
||||
@ -1305,11 +1302,11 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
if($packet->protocol1 !== ProtocolInfo::CURRENT_PROTOCOL){
|
||||
if($packet->protocol1 < ProtocolInfo::CURRENT_PROTOCOL){
|
||||
$pk = new LoginStatusPacket;
|
||||
$pk = new LoginStatusPacket();
|
||||
$pk->status = 1;
|
||||
$this->dataPacket($pk);
|
||||
}else{
|
||||
$pk = new LoginStatusPacket;
|
||||
$pk = new LoginStatusPacket();
|
||||
$pk->status = 2;
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
@ -1411,7 +1408,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->inventory->setHeldItemSlot(0);
|
||||
}
|
||||
|
||||
$pk = new LoginStatusPacket;
|
||||
$pk = new LoginStatusPacket();
|
||||
$pk->status = 0;
|
||||
$this->dataPacket($pk);
|
||||
|
||||
@ -1423,7 +1420,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
$this->dead = false;
|
||||
|
||||
$pk = new StartGamePacket;
|
||||
$pk = new StartGamePacket();
|
||||
$pk->seed = $this->level->getSeed();
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
@ -1438,9 +1435,10 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
$pk = new SetTimePacket();
|
||||
$pk->time = $this->level->getTime();
|
||||
$pk->started = $this->level->stopTime == false;
|
||||
$this->dataPacket($pk);
|
||||
|
||||
$pk = new SetSpawnPositionPacket;
|
||||
$pk = new SetSpawnPositionPacket();
|
||||
$pk->x = (int) $spawnPosition->x;
|
||||
$pk->y = (int) $spawnPosition->y;
|
||||
$pk->z = (int) $spawnPosition->z;
|
||||
@ -1453,6 +1451,10 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->dead = true;
|
||||
}
|
||||
|
||||
$pk = new SetDifficultyPacket();
|
||||
$pk->difficulty = $this->server->getDifficulty();
|
||||
$this->dataPacket($pk);
|
||||
|
||||
$this->server->getLogger()->info(TextFormat::AQUA . $this->username . TextFormat::WHITE . "[/" . $this->ip . ":" . $this->port . "] logged in with entity id " . $this->id . " at (" . $this->level->getName() . ", " . round($this->x, 4) . ", " . round($this->y, 4) . ", " . round($this->z, 4) . ")");
|
||||
|
||||
|
||||
@ -1469,17 +1471,21 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
$newPos = new Vector3($packet->x, $packet->y, $packet->z);
|
||||
|
||||
$revert = ($this->dead === true or $this->spawned !== true);
|
||||
$revert = false;
|
||||
if($this->dead === true or $this->spawned !== true){
|
||||
$revert = true;
|
||||
$this->forceMovement = new Vector3($this->x, $this->y, $this->z);
|
||||
}
|
||||
|
||||
if($revert or ($this->forceMovement instanceof Vector3 and $newPos->distance($this->forceMovement) > 0.2)){
|
||||
if($this->forceMovement instanceof Vector3 and ($revert or $newPos->distance($this->forceMovement) > 0.2)){
|
||||
$pk = new MovePlayerPacket();
|
||||
$pk->eid = 0;
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y + $this->getEyeHeight();
|
||||
$pk->z = $this->z;
|
||||
$pk->bodyYaw = $this->yaw;
|
||||
$pk->pitch = $this->pitch;
|
||||
$pk->yaw = $this->yaw;
|
||||
$pk->x = $this->forceMovement->x;
|
||||
$pk->y = $this->forceMovement->y + $this->getEyeHeight() + 0.01;
|
||||
$pk->z = $this->forceMovement->z;
|
||||
$pk->bodyYaw = $packet->bodyYaw;
|
||||
$pk->pitch = $packet->pitch;
|
||||
$pk->yaw = $packet->yaw;
|
||||
$pk->teleport = true;
|
||||
$this->directDataPacket($pk);
|
||||
}else{
|
||||
@ -1555,32 +1561,14 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
break;
|
||||
case ProtocolInfo::USE_ITEM_PACKET:
|
||||
if($this->spawned === false or $this->dead === true or $this->blocked){
|
||||
break;
|
||||
}
|
||||
|
||||
$blockVector = new Vector3($packet->x, $packet->y, $packet->z);
|
||||
|
||||
$this->craftingType = 0;
|
||||
|
||||
if(($this->spawned === false or $this->blocked === true or $this->dead === true) and $packet->face >= 0 and $packet->face <= 5){
|
||||
$target = $this->level->getBlock($blockVector);
|
||||
$block = $target->getSide($packet->face);
|
||||
|
||||
$pk = new UpdateBlockPacket;
|
||||
$pk->x = $target->x;
|
||||
$pk->y = $target->y;
|
||||
$pk->z = $target->z;
|
||||
$pk->block = $target->getID();
|
||||
$pk->meta = $target->getDamage();
|
||||
$this->dataPacket($pk);
|
||||
|
||||
$pk = new UpdateBlockPacket;
|
||||
$pk->x = $block->x;
|
||||
$pk->y = $block->y;
|
||||
$pk->z = $block->z;
|
||||
$pk->block = $block->getID();
|
||||
$pk->meta = $block->getDamage();
|
||||
$this->dataPacket($pk);
|
||||
break;
|
||||
}
|
||||
|
||||
$packet->eid = $this->id;
|
||||
|
||||
if($packet->face >= 0 and $packet->face <= 5){ //Use Block, place
|
||||
@ -1599,7 +1587,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}elseif($this->inventory->getItemInHand()->getID() !== $packet->item or (($damage = $this->inventory->getItemInHand()->getDamage()) !== $packet->meta and $damage !== null)){
|
||||
$this->inventory->sendHeldItem($this);
|
||||
}else{
|
||||
$item = clone $this->inventory->getItemInHand();
|
||||
$item = $this->inventory->getItemInHand();
|
||||
//TODO: Implement adventure mode checks
|
||||
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){
|
||||
$this->inventory->setItemInHand($item, $this);
|
||||
@ -1610,7 +1598,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$target = $this->level->getBlock($blockVector);
|
||||
$block = $target->getSide($packet->face);
|
||||
|
||||
$pk = new UpdateBlockPacket;
|
||||
$pk = new UpdateBlockPacket();
|
||||
$pk->x = $target->x;
|
||||
$pk->y = $target->y;
|
||||
$pk->z = $target->z;
|
||||
@ -1618,7 +1606,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$pk->meta = $target->getDamage();
|
||||
$this->dataPacket($pk);
|
||||
|
||||
$pk = new UpdateBlockPacket;
|
||||
$pk = new UpdateBlockPacket();
|
||||
$pk->x = $block->x;
|
||||
$pk->y = $block->y;
|
||||
$pk->z = $block->z;
|
||||
@ -1627,7 +1615,60 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->dataPacket($pk);
|
||||
break;
|
||||
}elseif($packet->face === 0xff){
|
||||
//TODO: add event
|
||||
if($this->isCreative()){
|
||||
$item = $this->inventory->getItemInHand();
|
||||
}elseif($this->inventory->getItemInHand()->getID() !== $packet->item or (($damage = $this->inventory->getItemInHand()->getDamage()) !== $packet->meta and $damage !== null)){
|
||||
$this->inventory->sendHeldItem($this);
|
||||
break;
|
||||
}else{
|
||||
$item = $this->inventory->getItemInHand();
|
||||
}
|
||||
$target = $this->level->getBlock($blockVector);
|
||||
|
||||
$ev = new PlayerInteractEvent($this, $item, $target, $packet->face);
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
|
||||
if($ev->isCancelled()){
|
||||
$this->inventory->sendHeldItem($this);
|
||||
break;
|
||||
}
|
||||
|
||||
if($item->getID() === Item::SNOWBALL){
|
||||
$nbt = new Compound("", [
|
||||
"Pos" => new Enum("Pos", [
|
||||
new Double("", $this->x),
|
||||
new Double("", $this->y + $this->getEyeHeight()),
|
||||
new Double("", $this->z)
|
||||
]),
|
||||
"Motion" => new Enum("Motion", [
|
||||
new Double("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)),
|
||||
new Double("", -sin($this->pitch / 180 * M_PI)),
|
||||
new Double("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))
|
||||
]),
|
||||
"Rotation" => new Enum("Rotation", [
|
||||
new Float("", $this->yaw),
|
||||
new Float("", $this->pitch)
|
||||
]),
|
||||
]);
|
||||
|
||||
$f = 1.5;
|
||||
$snowball = Entity::createEntity("Snowball", $this->chunk, $nbt, $this);
|
||||
$snowball->setMotion($snowball->getMotion()->multiply($f));
|
||||
if($this->isSurvival()){
|
||||
$this->inventory->removeItem(Item::get(Item::SNOWBALL, 0, 1), $this);
|
||||
}
|
||||
if($snowball instanceof Projectile){
|
||||
$this->server->getPluginManager()->callEvent($projectileEv = new ProjectileLaunchEvent($snowball));
|
||||
if($projectileEv->isCancelled()){
|
||||
$snowball->kill();
|
||||
}else{
|
||||
$snowball->spawnToAll();
|
||||
}
|
||||
}else{
|
||||
$snowball->spawnToAll();
|
||||
}
|
||||
}
|
||||
$this->inAction = true;
|
||||
$this->startAction = microtime(true);
|
||||
$this->sendMetadata($this->getViewers());
|
||||
@ -1671,7 +1712,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
]);
|
||||
|
||||
$f = 1.5;
|
||||
$ev = new EntityShootBowEvent($this, $bow, new Arrow($this->chunk, $nbt, $this), $f);
|
||||
$ev = new EntityShootBowEvent($this, $bow, Entity::createEntity("Arrow", $this->chunk, $nbt, $this), $f);
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
|
||||
@ -1680,7 +1721,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}else{
|
||||
$ev->getProjectile()->setMotion($ev->getProjectile()->getMotion()->multiply($ev->getForce()));
|
||||
if($this->isSurvival()){
|
||||
$this->inventory->removeItem(Item::get(Item::ARROW, 0, 1));
|
||||
$this->inventory->removeItem(Item::get(Item::ARROW, 0, 1), $this);
|
||||
$bow->setDamage($bow->getDamage() + 1);
|
||||
$this->inventory->setItemInHand($bow, $this);
|
||||
if($bow->getDamage() >= 385){
|
||||
@ -1736,7 +1777,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$target = $this->level->getBlock($vector);
|
||||
$tile = $this->level->getTile($vector);
|
||||
|
||||
$pk = new UpdateBlockPacket;
|
||||
$pk = new UpdateBlockPacket();
|
||||
$pk->x = $target->x;
|
||||
$pk->y = $target->y;
|
||||
$pk->z = $target->z;
|
||||
@ -1753,7 +1794,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
break;
|
||||
|
||||
case ProtocolInfo::INTERACT_PACKET:
|
||||
if($this->spawned === false or $this->dead === true){
|
||||
if($this->spawned === false or $this->dead === true or $this->blocked){
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1771,7 +1812,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$cancelled = true;
|
||||
}
|
||||
|
||||
if($target instanceof Entity and $this->getGamemode() !== Player::VIEW and $this->blocked === false and $this->dead !== true and $target->dead !== true){
|
||||
if($target instanceof Entity and $this->getGamemode() !== Player::VIEW and $this->dead !== true and $target->dead !== true){
|
||||
if($target instanceof DroppedItem or $target instanceof Arrow){
|
||||
$this->kick("Attempting to attack an invalid entity");
|
||||
$this->server->getLogger()->warning("Player ". $this->getName() ." tried to attack an invalid entity");
|
||||
@ -1847,14 +1888,16 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
$damage[EntityDamageEvent::MODIFIER_ARMOR] = -intval($damage[EntityDamageEvent::MODIFIER_BASE] * $points * 0.04);
|
||||
$damage[EntityDamageEvent::MODIFIER_ARMOR] = -floor($damage[EntityDamageEvent::MODIFIER_BASE] * $points * 0.04);
|
||||
}
|
||||
|
||||
$ev = new EntityDamageByEntityEvent($this, $target, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $damage);
|
||||
if($cancelled){
|
||||
$ev->setCancelled();
|
||||
}
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
|
||||
$target->attack($ev->getFinalDamage(), $ev);
|
||||
|
||||
if($ev->isCancelled()){
|
||||
if($item->isTool() and $this->isSurvival()){
|
||||
$this->inventory->sendContents($this);
|
||||
@ -1862,8 +1905,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
break;
|
||||
}
|
||||
|
||||
$target->attack($ev->getFinalDamage(), $ev);
|
||||
|
||||
if($item->isTool() and $this->isSurvival()){
|
||||
if($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()){
|
||||
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1), $this);
|
||||
@ -1975,7 +2016,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
--$slot->count;
|
||||
$this->inventory->setItemInHand($slot, $this);
|
||||
if($slot->getID() === Item::MUSHROOM_STEW or $slot->getID() === Item::BEETROOT_SOUP){
|
||||
$this->inventory->addItem(Item::get(Item::BOWL, 0, 1));
|
||||
$this->inventory->addItem(Item::get(Item::BOWL, 0, 1), $this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2084,10 +2125,10 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
if($this->currentTransaction === null or $this->currentTransaction->getCreationTime() < (microtime(true) - 0.4)){
|
||||
if($this->currentTransaction instanceof SimpleTransactionGroup){
|
||||
foreach($this->currentTransaction->getInventories() as $inventory){
|
||||
$inventory->sendContents($inventory->getViewers());
|
||||
if($inventory instanceof PlayerInventory){
|
||||
$inventory->sendArmorContents($inventory->getViewers());
|
||||
$inventory->sendArmorContents($this);
|
||||
}
|
||||
$inventory->sendContents($this);
|
||||
}
|
||||
}
|
||||
$this->currentTransaction = new SimpleTransactionGroup($this);
|
||||
@ -2145,7 +2186,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
case Item::CAKE:
|
||||
//TODO: detect complex recipes like cake that leave remains
|
||||
$this->awardAchievement("bakeCake");
|
||||
$this->inventory->addItem(Item::get(Item::BUCKET, 0, 3));
|
||||
$this->inventory->addItem(Item::get(Item::BUCKET, 0, 3), $this);
|
||||
break;
|
||||
case Item::STONE_PICKAXE:
|
||||
case Item::GOLD_PICKAXE:
|
||||
@ -2182,7 +2223,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
$this->craftingType = 0;
|
||||
|
||||
$t = $this->level->getTile($v = new Vector3($packet->x, $packet->y, $packet->z));
|
||||
$t = $this->level->getTile(new Vector3($packet->x, $packet->y, $packet->z));
|
||||
if($t instanceof Sign){
|
||||
$nbt = new NBT(NBT::LITTLE_ENDIAN);
|
||||
$nbt->read($packet->namedtag);
|
||||
@ -2190,7 +2231,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
if($nbt["id"] !== Tile::SIGN){
|
||||
$t->spawnTo($this);
|
||||
}else{
|
||||
$ev = new SignChangeEvent($this->level->getBlock($v), $this, [
|
||||
$ev = new SignChangeEvent($t->getBlock(), $this, [
|
||||
$nbt["Text1"], $nbt["Text2"], $nbt["Text3"], $nbt["Text4"]
|
||||
]);
|
||||
|
||||
@ -2245,7 +2286,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$mes = explode("\n", $message);
|
||||
foreach($mes as $m){
|
||||
if($m !== ""){
|
||||
$pk = new MessagePacket;
|
||||
$pk = new MessagePacket();
|
||||
$pk->source = ""; //Do not use this ;)
|
||||
$pk->message = $m;
|
||||
$this->dataPacket($pk);
|
||||
@ -2273,9 +2314,17 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
$this->interface->close($this, $reason);
|
||||
$this->level->freeAllChunks($this);
|
||||
foreach($this->windowIndex as $window){
|
||||
$this->removeWindow($window);
|
||||
}
|
||||
|
||||
$this->interface->close($this, $reason);
|
||||
|
||||
$chunkX = $chunkZ = null;
|
||||
foreach($this->usedChunks as $index => $d){
|
||||
Level::getXZ($index, $chunkX, $chunkZ);
|
||||
$this->level->freeChunk($chunkX, $chunkZ, $this);
|
||||
}
|
||||
|
||||
parent::close();
|
||||
|
||||
@ -2284,6 +2333,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
if(isset($ev) and $this->username != "" and $this->spawned !== false and $ev->getQuitMessage() != ""){
|
||||
$this->server->broadcastMessage($ev->getQuitMessage());
|
||||
}
|
||||
|
||||
$this->server->getPluginManager()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this);
|
||||
$this->spawned = false;
|
||||
$this->server->getLogger()->info(TextFormat::AQUA . $this->username . TextFormat::WHITE . "[/" . $this->ip . ":" . $this->port . "] logged out due to " . str_replace(["\n", "\r"], [" ", ""], $reason));
|
||||
@ -2291,18 +2341,26 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->windowIndex = [];
|
||||
$this->usedChunks = [];
|
||||
$this->loadQueue = [];
|
||||
$this->hasSpawned = [];
|
||||
$this->spawnPosition = null;
|
||||
$this->perm->clearPermissions();
|
||||
$this->perm = null;
|
||||
unset($this->buffer);
|
||||
}
|
||||
|
||||
$this->server->removePlayer($this);
|
||||
}
|
||||
|
||||
public function __debugInfo(){
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles player data saving
|
||||
*/
|
||||
public function save(){
|
||||
if($this->closed){
|
||||
throw new \Exception("Tried to save closed player");
|
||||
throw new \InvalidStateException("Tried to save closed player");
|
||||
}
|
||||
|
||||
parent::saveNBT();
|
||||
@ -2416,6 +2474,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
case EntityDamageEvent::CAUSE_BLOCK_EXPLOSION:
|
||||
case EntityDamageEvent::CAUSE_ENTITY_EXPLOSION:
|
||||
$message = $this->getName() . " blew up";
|
||||
break;
|
||||
|
||||
case EntityDamageEvent::CAUSE_MAGIC:
|
||||
case EntityDamageEvent::CAUSE_CUSTOM:
|
||||
|
||||
@ -2462,7 +2523,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
if($this->dead === true){
|
||||
return;
|
||||
}
|
||||
if(($this->getGamemode() & 0x01) === 1){
|
||||
if($this->isCreative()){
|
||||
if($source instanceof EntityDamageEvent){
|
||||
$cause = $source->getCause();
|
||||
}else{
|
||||
@ -2474,6 +2535,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
and $cause !== EntityDamageEvent::CAUSE_SUICIDE
|
||||
and $cause !== EntityDamageEvent::CAUSE_VOID
|
||||
){
|
||||
if($source instanceof EntityDamageEvent){
|
||||
$source->setCancelled();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2481,6 +2545,10 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
parent::attack($damage, $source);
|
||||
|
||||
if($source instanceof EntityDamageEvent and $source->isCancelled()){
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->getLastDamageCause() === $source){
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->eid = 0;
|
||||
@ -2513,13 +2581,22 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
public function teleport(Vector3 $pos, $yaw = null, $pitch = null){
|
||||
if(parent::teleport($pos, $yaw, $pitch)){
|
||||
|
||||
foreach($this->windowIndex as $window){
|
||||
if($window === $this->inventory){
|
||||
continue;
|
||||
}
|
||||
$this->removeWindow($window);
|
||||
}
|
||||
|
||||
$this->airTicks = 300;
|
||||
$this->fallDistance = 0;
|
||||
$this->orderChunks();
|
||||
$this->nextChunkOrderRun = 0;
|
||||
$this->forceMovement = $pos;
|
||||
$this->newPosition = $pos;
|
||||
|
||||
$pk = new MovePlayerPacket;
|
||||
$pk = new MovePlayerPacket();
|
||||
$pk->eid = 0;
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y + $this->getEyeHeight();
|
||||
@ -2601,4 +2678,4 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -65,16 +65,15 @@ namespace {
|
||||
}
|
||||
|
||||
namespace pocketmine {
|
||||
use LogLevel;
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\wizard\Installer;
|
||||
|
||||
const VERSION = "Alpha_1.4dev";
|
||||
const API_VERSION = "1.6.0";
|
||||
const API_VERSION = "1.7.1";
|
||||
const CODENAME = "絶好(Zekkou)ケーキ(Cake)";
|
||||
const MINECRAFT_VERSION = "v0.9.5 alpha";
|
||||
const MINECRAFT_VERSION = "v0.10.0 alpha";
|
||||
|
||||
/*
|
||||
* Startup code. Do not look at it, it may harm you.
|
||||
@ -122,11 +121,14 @@ namespace pocketmine {
|
||||
|
||||
$opts = getopt("", ["enable-ansi", "disable-ansi", "data:", "plugins:", "no-wizard", "enable-profiler"]);
|
||||
|
||||
define("pocketmine\\DATA", isset($opts["data"]) ? realpath($opts["data"]) . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR);
|
||||
define("pocketmine\\PLUGIN_PATH", isset($opts["plugins"]) ? realpath($opts["plugins"]) . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
|
||||
define("pocketmine\\DATA", isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR);
|
||||
define("pocketmine\\PLUGIN_PATH", isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
|
||||
|
||||
define("pocketmine\\ANSI", (Utils::getOS() !== "win" or isset($opts["enable-ansi"])) and !isset($opts["disable-ansi"]));
|
||||
|
||||
|
||||
@mkdir(\pocketmine\DATA, 0777, true);
|
||||
|
||||
//Logger has a dependency on timezone, so we'll set it to UTC until we can get the actual timezone.
|
||||
date_default_timezone_set("UTC");
|
||||
$logger = new MainLogger(\pocketmine\DATA . "server.log", \pocketmine\ANSI);
|
||||
@ -134,7 +136,7 @@ namespace pocketmine {
|
||||
if(!ini_get("date.timezone")){
|
||||
if(($timezone = detect_system_timezone()) and date_default_timezone_set($timezone)){
|
||||
//Success! Timezone has already been set and validated in the if statement.
|
||||
//This here is just for redundancy just in case some stupid program wants to read timezone data from the ini.
|
||||
//This here is just for redundancy just in case some program wants to read timezone data from the ini.
|
||||
ini_set("date.timezone", $timezone);
|
||||
}else{
|
||||
//If system timezone detection fails or timezone is an invalid value.
|
||||
@ -153,7 +155,8 @@ namespace pocketmine {
|
||||
}
|
||||
}else{
|
||||
/*
|
||||
* This is here so that stupid idiots don't come to us complaining and fill up the issue tracker when they put an incorrect timezone abbreviation in php.ini apparently.
|
||||
* This is here so that people don't come to us complaining and fill up the issue tracker when they put
|
||||
* an incorrect timezone abbreviation in php.ini apparently.
|
||||
*/
|
||||
$default_timezone = date_default_timezone_get();
|
||||
if(strpos($default_timezone, "/") === false){
|
||||
@ -166,13 +169,27 @@ namespace pocketmine {
|
||||
function detect_system_timezone(){
|
||||
switch(Utils::getOS()){
|
||||
case 'win':
|
||||
$regex = '/(?:Time Zone:\s*\()(UTC)(\+*\-*\d*\d*\:*\d*\d*)(?:\))/';
|
||||
$regex = '/(UTC)(\+*\-*\d*\d*\:*\d*\d*)/';
|
||||
|
||||
exec("systeminfo", $output);
|
||||
/*
|
||||
* wmic timezone get Caption
|
||||
* Get the timezone offset
|
||||
*
|
||||
* Sample Output var_dump
|
||||
* array(3) {
|
||||
* [0] =>
|
||||
* string(7) "Caption"
|
||||
* [1] =>
|
||||
* string(20) "(UTC+09:30) Adelaide"
|
||||
* [2] =>
|
||||
* string(0) ""
|
||||
* }
|
||||
*/
|
||||
exec("wmic timezone get Caption", $output);
|
||||
|
||||
$string = trim(implode("\n", $output));
|
||||
|
||||
//Detect the Time Zone string in systeminfo
|
||||
//Detect the Time Zone string
|
||||
preg_match($regex, $string, $matches);
|
||||
|
||||
if(!isset($matches[2]))
|
||||
@ -327,55 +344,7 @@ namespace pocketmine {
|
||||
return rtrim(str_replace(["\\", ".php", "phar://", rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), "/"), rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH), "/")], ["/", "", "", "", ""], $path), "/");
|
||||
}
|
||||
|
||||
function error_handler($errno, $errstr, $errfile, $errline, $context, $trace = null){
|
||||
global $lastError;
|
||||
if(error_reporting() === 0){ //@ error-con..trol
|
||||
return false;
|
||||
}
|
||||
$errorConversion = [
|
||||
E_ERROR => "E_ERROR",
|
||||
E_WARNING => "E_WARNING",
|
||||
E_PARSE => "E_PARSE",
|
||||
E_NOTICE => "E_NOTICE",
|
||||
E_CORE_ERROR => "E_CORE_ERROR",
|
||||
E_CORE_WARNING => "E_CORE_WARNING",
|
||||
E_COMPILE_ERROR => "E_COMPILE_ERROR",
|
||||
E_COMPILE_WARNING => "E_COMPILE_WARNING",
|
||||
E_USER_ERROR => "E_USER_ERROR",
|
||||
E_USER_WARNING => "E_USER_WARNING",
|
||||
E_USER_NOTICE => "E_USER_NOTICE",
|
||||
E_STRICT => "E_STRICT",
|
||||
E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
|
||||
E_DEPRECATED => "E_DEPRECATED",
|
||||
E_USER_DEPRECATED => "E_USER_DEPRECATED",
|
||||
];
|
||||
$type = ($errno === E_ERROR or $errno === E_USER_ERROR) ? LogLevel::ERROR : (($errno === E_USER_WARNING or $errno === E_WARNING) ? LogLevel::WARNING : LogLevel::NOTICE);
|
||||
$errno = isset($errorConversion[$errno]) ? $errorConversion[$errno] : $errno;
|
||||
if(($pos = strpos($errstr, "\n")) !== false){
|
||||
$errstr = substr($errstr, 0, $pos);
|
||||
}
|
||||
$logger = MainLogger::getLogger();
|
||||
$oldFile = $errfile;
|
||||
$errfile = cleanPath($errfile);
|
||||
$logger->log($type, "An $errno error happened: \"$errstr\" in \"$errfile\" at line $errline");
|
||||
|
||||
foreach(($trace = getTrace($trace === null ? 3 : 0, $trace)) as $i => $line){
|
||||
$logger->debug($line);
|
||||
}
|
||||
|
||||
$lastError = [
|
||||
"type" => $type,
|
||||
"message" => $errstr,
|
||||
"fullFile" => $oldFile,
|
||||
"file" => $errfile,
|
||||
"line" => $errline,
|
||||
"trace" => $trace
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
set_error_handler("\\pocketmine\\error_handler", E_ALL);
|
||||
set_error_handler([\ExceptionHandler::class, "handler"], -1);
|
||||
|
||||
$errors = 0;
|
||||
|
||||
|
@ -31,6 +31,15 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\ConsoleCommandSender;
|
||||
use pocketmine\command\PluginIdentifiableCommand;
|
||||
use pocketmine\command\SimpleCommandMap;
|
||||
use pocketmine\entity\Arrow;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\FallingSand;
|
||||
use pocketmine\entity\Human;
|
||||
use pocketmine\entity\Item as DroppedItem;
|
||||
use pocketmine\entity\PrimedTNT;
|
||||
use pocketmine\entity\Snowball;
|
||||
use pocketmine\entity\Villager;
|
||||
use pocketmine\entity\Zombie;
|
||||
use pocketmine\event\HandlerList;
|
||||
use pocketmine\event\level\LevelInitEvent;
|
||||
use pocketmine\event\level\LevelLoadEvent;
|
||||
@ -78,11 +87,17 @@ use pocketmine\plugin\PluginManager;
|
||||
use pocketmine\scheduler\CallbackTask;
|
||||
use pocketmine\scheduler\SendUsageTask;
|
||||
use pocketmine\scheduler\ServerScheduler;
|
||||
use pocketmine\tile\Chest;
|
||||
use pocketmine\tile\Furnace;
|
||||
use pocketmine\tile\Sign;
|
||||
use pocketmine\tile\Tile;
|
||||
use pocketmine\updater\AutoUpdater;
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\Cache;
|
||||
use pocketmine\utils\Config;
|
||||
use pocketmine\utils\LevelException;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\ServerException;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\TextWrapper;
|
||||
use pocketmine\utils\Utils;
|
||||
@ -113,6 +128,8 @@ class Server{
|
||||
/** @var bool */
|
||||
private $isRunning = true;
|
||||
|
||||
private $hasStopped = false;
|
||||
|
||||
/** @var PluginManager */
|
||||
private $pluginManager = null;
|
||||
|
||||
@ -610,9 +627,16 @@ class Server{
|
||||
* @param string $payload
|
||||
*/
|
||||
public function handlePacket($address, $port, $payload){
|
||||
if(strlen($payload) > 2 and substr($payload, 0, 2) === "\xfe\xfd" and $this->queryHandler instanceof QueryHandler){
|
||||
$this->queryHandler->handle($address, $port, $payload);
|
||||
} //TODO: add raw packet events
|
||||
try{
|
||||
if(strlen($payload) > 2 and substr($payload, 0, 2) === "\xfe\xfd" and $this->queryHandler instanceof QueryHandler){
|
||||
$this->queryHandler->handle($address, $port, $payload);
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
if($this->logger instanceof MainLogger){
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
}
|
||||
//TODO: add raw packet events
|
||||
}
|
||||
|
||||
/**
|
||||
@ -643,7 +667,7 @@ class Server{
|
||||
$result = $this->getPlayerExact($name);
|
||||
|
||||
if($result === null){
|
||||
$result = new OfflinePlayer($this, $name);
|
||||
return new OfflinePlayer($this, $name);
|
||||
}
|
||||
|
||||
return $result;
|
||||
@ -930,11 +954,11 @@ class Server{
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws LevelException
|
||||
*/
|
||||
public function loadLevel($name){
|
||||
if(trim($name) === ""){
|
||||
throw new \Exception("Invalid empty level name");
|
||||
throw new LevelException("Invalid empty level name");
|
||||
}
|
||||
if($this->isLevelLoaded($name)){
|
||||
return true;
|
||||
@ -1083,7 +1107,7 @@ class Server{
|
||||
return false;
|
||||
}
|
||||
|
||||
$seed = $seed === null ? Binary::readInt(Utils::getRandomBytes(4, false)) : (int) $seed;
|
||||
$seed = $seed === null ? Binary::readInt(@Utils::getRandomBytes(4, false)) : (int) $seed;
|
||||
|
||||
if($generator !== null and class_exists($generator) and is_subclass_of($generator, Generator::class)){
|
||||
$generator = new $generator($options);
|
||||
@ -1427,11 +1451,12 @@ class Server{
|
||||
$this->autoloader = $autoloader;
|
||||
$this->logger = $logger;
|
||||
$this->filePath = $filePath;
|
||||
$this->dataPath = $dataPath;
|
||||
$this->pluginPath = $pluginPath;
|
||||
@mkdir($this->dataPath . "worlds/", 0777, true);
|
||||
@mkdir($this->dataPath . "players/", 0777);
|
||||
@mkdir($this->pluginPath, 0777);
|
||||
@mkdir($dataPath . "worlds/", 0777);
|
||||
@mkdir($dataPath . "players/", 0777);
|
||||
@mkdir($pluginPath, 0777);
|
||||
|
||||
$this->dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR;
|
||||
$this->pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
|
||||
|
||||
$this->entityMetadata = new EntityMetadataStore();
|
||||
$this->playerMetadata = new PlayerMetadataStore();
|
||||
@ -1488,7 +1513,7 @@ class Server{
|
||||
"level-type" => "DEFAULT",
|
||||
"enable-query" => true,
|
||||
"enable-rcon" => false,
|
||||
"rcon.password" => substr(base64_encode(Utils::getRandomBytes(20, false)), 3, 10),
|
||||
"rcon.password" => substr(base64_encode(@Utils::getRandomBytes(20, false)), 3, 10),
|
||||
"auto-save" => true,
|
||||
]);
|
||||
|
||||
@ -1534,12 +1559,12 @@ class Server{
|
||||
}
|
||||
|
||||
$this->logger->info("Starting Minecraft PE server on " . ($this->getIp() === "" ? "*" : $this->getIp()) . ":" . $this->getPort());
|
||||
define("BOOTUP_RANDOM", Utils::getRandomBytes(16));
|
||||
define("BOOTUP_RANDOM", @Utils::getRandomBytes(16));
|
||||
$this->serverID = Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() . $this->getPort()), 0, 8));
|
||||
|
||||
$this->addInterface($this->mainInterface = new RakLibInterface($this));
|
||||
|
||||
$this->logger->info("This server is running " . $this->getName() . " version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(true) . TextFormat::RESET . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0);
|
||||
$this->logger->info("This server is running " . $this->getName() . " version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(true) . TextFormat::WHITE . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0);
|
||||
$this->logger->info($this->getName() . " is distributed under the LGPL License", true, true, 0);
|
||||
|
||||
PluginManager::$pluginParentTimer = new TimingsHandler("** Plugins");
|
||||
@ -1548,6 +1573,9 @@ class Server{
|
||||
$this->consoleSender = new ConsoleCommandSender();
|
||||
$this->commandMap = new SimpleCommandMap($this);
|
||||
|
||||
$this->registerEntities();
|
||||
$this->registerTiles();
|
||||
|
||||
InventoryType::init();
|
||||
Block::init();
|
||||
Item::init();
|
||||
@ -1561,7 +1589,6 @@ class Server{
|
||||
|
||||
set_exception_handler([$this, "exceptionHandler"]);
|
||||
register_shutdown_function([$this, "crashDump"]);
|
||||
register_shutdown_function([$this, "forceShutdown"]);
|
||||
|
||||
$this->pluginManager->loadPlugins($this->pluginPath);
|
||||
|
||||
@ -1697,6 +1724,9 @@ class Server{
|
||||
foreach($players as $player){
|
||||
$player->dataPacket($packet);
|
||||
}
|
||||
if(isset($packet->__encapsulatedPacket)){
|
||||
unset($packet->__encapsulatedPacket);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1759,7 +1789,7 @@ class Server{
|
||||
*/
|
||||
public function dispatchCommand(CommandSender $sender, $commandLine){
|
||||
if(!($sender instanceof CommandSender)){
|
||||
throw new \Exception("CommandSender is not valid");
|
||||
throw new ServerException("CommandSender is not valid");
|
||||
}
|
||||
|
||||
if($this->commandMap->dispatch($sender, $commandLine)){
|
||||
@ -1827,40 +1857,54 @@ class Server{
|
||||
}
|
||||
|
||||
public function forceShutdown(){
|
||||
$this->shutdown();
|
||||
if($this->rcon instanceof RCON){
|
||||
$this->rcon->stop();
|
||||
if($this->hasStopped){
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->getProperty("settings.upnp-forwarding", false) === true){
|
||||
$this->logger->info("[UPnP] Removing port forward...");
|
||||
UPnP::RemovePortForward($this->getPort());
|
||||
try{
|
||||
$this->hasStopped = true;
|
||||
|
||||
$this->shutdown();
|
||||
if($this->rcon instanceof RCON){
|
||||
$this->rcon->stop();
|
||||
}
|
||||
|
||||
if($this->getProperty("settings.upnp-forwarding", false) === true){
|
||||
$this->logger->info("[UPnP] Removing port forward...");
|
||||
UPnP::RemovePortForward($this->getPort());
|
||||
}
|
||||
|
||||
$this->pluginManager->disablePlugins();
|
||||
|
||||
foreach($this->players as $player){
|
||||
$player->close(TextFormat::YELLOW . $player->getName() . " has left the game", $this->getProperty("settings.shutdown-message", "Server closed"));
|
||||
}
|
||||
|
||||
foreach($this->getLevels() as $level){
|
||||
$this->unloadLevel($level, true);
|
||||
}
|
||||
|
||||
if($this->generationManager instanceof GenerationRequestManager){
|
||||
$this->generationManager->shutdown();
|
||||
}
|
||||
|
||||
HandlerList::unregisterAll();
|
||||
|
||||
$this->scheduler->cancelAllTasks();
|
||||
$this->scheduler->mainThreadHeartbeat(PHP_INT_MAX);
|
||||
|
||||
$this->properties->save();
|
||||
|
||||
$this->console->kill();
|
||||
|
||||
foreach($this->interfaces as $interface){
|
||||
$interface->shutdown();
|
||||
}
|
||||
}catch (\Exception $e){
|
||||
$this->logger->emergency("Crashed while crashing, killing process");
|
||||
@kill(getmypid());
|
||||
}
|
||||
|
||||
$this->pluginManager->disablePlugins();
|
||||
|
||||
foreach($this->players as $player){
|
||||
$player->close(TextFormat::YELLOW . $player->getName() . " has left the game", $this->getProperty("settings.shutdown-message", "Server closed"));
|
||||
}
|
||||
|
||||
foreach($this->getLevels() as $level){
|
||||
$this->unloadLevel($level, true);
|
||||
}
|
||||
|
||||
if($this->generationManager instanceof GenerationRequestManager){
|
||||
$this->generationManager->shutdown();
|
||||
}
|
||||
|
||||
HandlerList::unregisterAll();
|
||||
$this->scheduler->cancelAllTasks();
|
||||
$this->scheduler->mainThreadHeartbeat(PHP_INT_MAX);
|
||||
|
||||
$this->properties->save();
|
||||
|
||||
$this->console->kill();
|
||||
foreach($this->interfaces as $interface){
|
||||
$interface->shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1929,25 +1973,52 @@ class Server{
|
||||
}
|
||||
}
|
||||
|
||||
public function exceptionHandler(\Exception $e){
|
||||
public function exceptionHandler(\Exception $e, $trace = null){
|
||||
if($e === null){
|
||||
return;
|
||||
}
|
||||
|
||||
error_handler(E_ERROR, $e->getMessage(), $e->getFile(), $e->getLine(), [], $e->getTrace());
|
||||
global $lastError;
|
||||
|
||||
$errstr = $e->getMessage();
|
||||
$errfile = $e->getFile();
|
||||
$errno = $e->getCode();
|
||||
$errline = $e->getLine();
|
||||
|
||||
$type = ($errno === E_ERROR or $errno === E_USER_ERROR) ? \LogLevel::ERROR : (($errno === E_USER_WARNING or $errno === E_WARNING) ? \LogLevel::WARNING : \LogLevel::NOTICE);
|
||||
if(($pos = strpos($errstr, "\n")) !== false){
|
||||
$errstr = substr($errstr, 0, $pos);
|
||||
}
|
||||
|
||||
$errfile = cleanPath($errfile);
|
||||
|
||||
if($this->logger instanceof MainLogger){
|
||||
$this->logger->logException($e, $trace);
|
||||
}
|
||||
|
||||
$lastError = [
|
||||
"type" => $type,
|
||||
"message" => $errstr,
|
||||
"fullFile" => $e->getFile(),
|
||||
"file" => $errfile,
|
||||
"line" => $errline,
|
||||
"trace" => @getTrace($trace === null ? 3 : 0, $trace)
|
||||
];
|
||||
|
||||
global $lastExceptionError, $lastError;
|
||||
$lastExceptionError = $lastError;
|
||||
$this->crashDump();
|
||||
$this->forceShutdown();
|
||||
kill(getmypid());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
public function crashDump(){
|
||||
if($this->isRunning === false){
|
||||
return;
|
||||
}
|
||||
ini_set("memory_limit", "-1"); //Fix error dump not dumped on memory problems
|
||||
$this->isRunning = false;
|
||||
$this->hasStopped = false;
|
||||
|
||||
ini_set("error_reporting", 0);
|
||||
ini_set("memory_limit", -1); //Fix error dump not dumped on memory problems
|
||||
$this->logger->emergency("An unrecoverable error has occurred and the server has crashed. Creating a crash dump");
|
||||
$dump = new CrashDump($this);
|
||||
|
||||
@ -1955,40 +2026,46 @@ class Server{
|
||||
|
||||
|
||||
if($this->getProperty("auto-report.enabled", true) !== false){
|
||||
$report = true;
|
||||
$plugin = $dump->getData()["plugin"];
|
||||
if(is_string($plugin)){
|
||||
$p = $this->pluginManager->getPlugin($plugin);
|
||||
if($p instanceof Plugin and !($p->getPluginLoader() instanceof PharPluginLoader)){
|
||||
return;
|
||||
$report = false;
|
||||
}
|
||||
}elseif(\Phar::running(true) == ""){
|
||||
return;
|
||||
$report = false;
|
||||
}
|
||||
if($dump->getData()["error"]["type"] === "E_PARSE" or $dump->getData()["error"]["type"] === "E_COMPILE_ERROR"){
|
||||
return;
|
||||
$report = false;
|
||||
}
|
||||
|
||||
$reply = Utils::postURL("http://" . $this->getProperty("auto-report.host", "crash.pocketmine.net") . "/submit/api", [
|
||||
"report" => "yes",
|
||||
"name" => $this->getName() . " " . $this->getPocketMineVersion(),
|
||||
"email" => "crash@pocketmine.net",
|
||||
"reportPaste" => base64_encode($dump->getEncodedData())
|
||||
]);
|
||||
if($report){
|
||||
$reply = Utils::postURL("http://" . $this->getProperty("auto-report.host", "crash.pocketmine.net") . "/submit/api", [
|
||||
"report" => "yes",
|
||||
"name" => $this->getName() . " " . $this->getPocketMineVersion(),
|
||||
"email" => "crash@pocketmine.net",
|
||||
"reportPaste" => base64_encode($dump->getEncodedData())
|
||||
]);
|
||||
|
||||
if(($data = json_decode($reply)) !== false and isset($data->crashId)){
|
||||
$reportId = $data->crashId;
|
||||
$reportUrl = $data->crashUrl;
|
||||
$this->logger->emergency("The crash dump has been automatically submitted to the Crash Archive. You can view it on $reportUrl or use the ID #$reportId.");
|
||||
if(($data = json_decode($reply)) !== false and isset($data->crashId)){
|
||||
$reportId = $data->crashId;
|
||||
$reportUrl = $data->crashUrl;
|
||||
$this->logger->emergency("The crash dump has been automatically submitted to the Crash Archive. You can view it on $reportUrl or use the ID #$reportId.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//$this->checkMemory();
|
||||
//$dump .= "Memory Usage Tracking: \r\n" . chunk_split(base64_encode(gzdeflate(implode(";", $this->memoryStats), 9))) . "\r\n";
|
||||
|
||||
$this->forceShutdown();
|
||||
@kill(getmypid());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
public function __debugInfo(){
|
||||
return get_class($this);
|
||||
return [];
|
||||
}
|
||||
|
||||
private function tickProcessor(){
|
||||
@ -2105,12 +2182,25 @@ class Server{
|
||||
if(($this->tickCounter & 0b1111) === 0){
|
||||
$this->titleTick();
|
||||
if(isset($this->queryHandler) and ($this->tickCounter & 0b111111111) === 0){
|
||||
$this->queryHandler->regenerateInfo();
|
||||
try{
|
||||
$this->queryHandler->regenerateInfo();
|
||||
}catch(\Exception $e){
|
||||
if($this->logger instanceof MainLogger){
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->generationManager->process();
|
||||
|
||||
if(($this->tickCounter % 100) === 0){
|
||||
foreach($this->levels as $level){
|
||||
$level->clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Timings::$serverTickTimer->stopTiming();
|
||||
|
||||
TimingsHandler::tick();
|
||||
@ -2129,4 +2219,22 @@ class Server{
|
||||
return true;
|
||||
}
|
||||
|
||||
private function registerEntities(){
|
||||
Entity::registerEntity(Arrow::class);
|
||||
Entity::registerEntity(DroppedItem::class);
|
||||
Entity::registerEntity(FallingSand::class);
|
||||
Entity::registerEntity(PrimedTNT::class);
|
||||
Entity::registerEntity(Snowball::class);
|
||||
Entity::registerEntity(Villager::class);
|
||||
Entity::registerEntity(Zombie::class);
|
||||
|
||||
Entity::registerEntity(Human::class, true);
|
||||
}
|
||||
|
||||
private function registerTiles(){
|
||||
Tile::registerTile(Chest::class);
|
||||
Tile::registerTile(Furnace::class);
|
||||
Tile::registerTile(Sign::class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -35,12 +35,8 @@ class Bed extends Transparent{
|
||||
$this->hardness = 1;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
protected function recalculateBoundingBox(){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -57,7 +53,7 @@ class Bed extends Transparent{
|
||||
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
|
||||
|
||||
if($player instanceof Player and !$isNight){
|
||||
$pk = new ChatPacket;
|
||||
$pk = new ChatPacket();
|
||||
$pk->message = "You can only sleep at night";
|
||||
$player->dataPacket($pk);
|
||||
|
||||
@ -81,7 +77,7 @@ class Bed extends Transparent{
|
||||
$b = $blockWest;
|
||||
}else{
|
||||
if($player instanceof Player){
|
||||
$pk = new ChatPacket;
|
||||
$pk = new ChatPacket();
|
||||
$pk->message = "This bed is incomplete";
|
||||
$player->dataPacket($pk);
|
||||
}
|
||||
@ -91,7 +87,7 @@ class Bed extends Transparent{
|
||||
}
|
||||
|
||||
if($player instanceof Player and $player->sleepOn($b) === false){
|
||||
$pk = new ChatPacket;
|
||||
$pk = new ChatPacket();
|
||||
$pk->message = "This bed is occupied";
|
||||
$player->dataPacket($pk);
|
||||
}
|
||||
|
@ -144,6 +144,7 @@ class Block extends Position implements Metadatable{
|
||||
const SUGARCANE_BLOCK = 83;
|
||||
|
||||
const FENCE = 85;
|
||||
const FENCE_OAK = 85;
|
||||
const PUMPKIN = 86;
|
||||
const NETHERRACK = 87;
|
||||
const SOUL_SAND = 88;
|
||||
@ -228,6 +229,17 @@ class Block extends Position implements Metadatable{
|
||||
const HARDENED_CLAY = 172;
|
||||
const COAL_BLOCK = 173;
|
||||
|
||||
const FENCE_GATE_SPRUCE = 183;
|
||||
const FENCE_GATE_BIRCH = 184;
|
||||
const FENCE_GATE_JUNGLE = 185;
|
||||
const FENCE_GATE_DARK_OAK = 186;
|
||||
const FENCE_GATE_ACACIA = 187;
|
||||
const FENCE_SPRUCE = 188;
|
||||
const FENCE_BIRCH = 189;
|
||||
const FENCE_JUNGLE = 190;
|
||||
const FENCE_DARK_OAK = 191;
|
||||
const FENCE_ACACIA = 192;
|
||||
|
||||
const PODZOL = 243;
|
||||
const BEETROOT_BLOCK = 244;
|
||||
const STONECUTTER = 245;
|
||||
@ -354,7 +366,16 @@ class Block extends Position implements Metadatable{
|
||||
[Item::WOODEN_DOOR, 0],
|
||||
[Item::TRAPDOOR, 0],
|
||||
[Item::FENCE, 0],
|
||||
[Item::FENCE_SPRUCE, 0],
|
||||
[Item::FENCE_BIRCH, 0],
|
||||
[Item::FENCE_DARK_OAK, 0],
|
||||
[Item::FENCE_JUNGLE, 0],
|
||||
[Item::FENCE_GATE, 0],
|
||||
[Item::FENCE_GATE_BIRCH, 0],
|
||||
[Item::FENCE_GATE_SPRUCE, 0],
|
||||
[Item::FENCE_GATE_DARK_OAK, 0],
|
||||
[Item::FENCE_GATE_JUNGLE, 0],
|
||||
[Item::FENCE_GATE_ACACIA, 0],
|
||||
[Item::IRON_BARS, 0],
|
||||
[Item::BED, 0],
|
||||
[Item::BOOKSHELF, 0],
|
||||
@ -505,14 +526,13 @@ class Block extends Position implements Metadatable{
|
||||
|
||||
];
|
||||
|
||||
/** @var Block[] */
|
||||
public static $list = [];
|
||||
/** @var \SplFixedArray */
|
||||
public static $list = null;
|
||||
protected $id;
|
||||
protected $meta;
|
||||
protected $name = "Unknown";
|
||||
protected $breakTime = 0.20;
|
||||
protected $hardness = 10;
|
||||
protected $boundingBox = null;
|
||||
public $hasEntityCollision = false;
|
||||
public $isActivable = false;
|
||||
public $breakable = true;
|
||||
@ -529,146 +549,159 @@ class Block extends Position implements Metadatable{
|
||||
public $z = 0;
|
||||
public $frictionFactor = 0.6;
|
||||
|
||||
/** @var AxisAlignedBB */
|
||||
protected $boundingBox = null;
|
||||
|
||||
public static function init(){
|
||||
if(count(self::$list) === 0){
|
||||
self::$list = [
|
||||
self::AIR => Air::class,
|
||||
self::STONE => Stone::class,
|
||||
self::GRASS => Grass::class,
|
||||
self::DIRT => Dirt::class,
|
||||
self::COBBLESTONE => Cobblestone::class,
|
||||
self::PLANKS => Planks::class,
|
||||
self::SAPLING => Sapling::class,
|
||||
self::BEDROCK => Bedrock::class,
|
||||
self::WATER => Water::class,
|
||||
self::STILL_WATER => StillWater::class,
|
||||
self::LAVA => Lava::class,
|
||||
self::STILL_LAVA => StillLava::class,
|
||||
self::SAND => Sand::class,
|
||||
self::GRAVEL => Gravel::class,
|
||||
self::GOLD_ORE => GoldOre::class,
|
||||
self::IRON_ORE => IronOre::class,
|
||||
self::COAL_ORE => CoalOre::class,
|
||||
self::WOOD => Wood::class,
|
||||
self::LEAVES => Leaves::class,
|
||||
self::SPONGE => Sponge::class,
|
||||
self::GLASS => Glass::class,
|
||||
self::LAPIS_ORE => LapisOre::class,
|
||||
self::LAPIS_BLOCK => Lapis::class,
|
||||
self::SANDSTONE => Sandstone::class,
|
||||
self::BED_BLOCK => Bed::class,
|
||||
self::COBWEB => Cobweb::class,
|
||||
self::TALL_GRASS => TallGrass::class,
|
||||
self::DEAD_BUSH => DeadBush::class,
|
||||
self::WOOL => Wool::class,
|
||||
self::DANDELION => Dandelion::class,
|
||||
self::POPPY => CyanFlower::class,
|
||||
self::BROWN_MUSHROOM => BrownMushroom::class,
|
||||
self::RED_MUSHROOM => RedMushroom::class,
|
||||
self::GOLD_BLOCK => Gold::class,
|
||||
self::IRON_BLOCK => Iron::class,
|
||||
self::DOUBLE_SLAB => DoubleSlab::class,
|
||||
self::SLAB => Slab::class,
|
||||
self::BRICKS_BLOCK => Bricks::class,
|
||||
self::TNT => TNT::class,
|
||||
self::BOOKSHELF => Bookshelf::class,
|
||||
self::MOSS_STONE => MossStone::class,
|
||||
self::OBSIDIAN => Obsidian::class,
|
||||
self::TORCH => Torch::class,
|
||||
self::FIRE => Fire::class,
|
||||
self::MONSTER_SPAWNER => MonsterSpawner::class,
|
||||
self::WOOD_STAIRS => WoodStairs::class,
|
||||
self::CHEST => Chest::class,
|
||||
if(self::$list === null){
|
||||
self::$list = new \SplFixedArray(256);
|
||||
self::$list[self::AIR] = Air::class;;
|
||||
self::$list[self::STONE] = Stone::class;;
|
||||
self::$list[self::GRASS] = Grass::class;;
|
||||
self::$list[self::DIRT] = Dirt::class;;
|
||||
self::$list[self::COBBLESTONE] = Cobblestone::class;;
|
||||
self::$list[self::PLANKS] = Planks::class;;
|
||||
self::$list[self::SAPLING] = Sapling::class;;
|
||||
self::$list[self::BEDROCK] = Bedrock::class;;
|
||||
self::$list[self::WATER] = Water::class;;
|
||||
self::$list[self::STILL_WATER] = StillWater::class;;
|
||||
self::$list[self::LAVA] = Lava::class;;
|
||||
self::$list[self::STILL_LAVA] = StillLava::class;;
|
||||
self::$list[self::SAND] = Sand::class;;
|
||||
self::$list[self::GRAVEL] = Gravel::class;;
|
||||
self::$list[self::GOLD_ORE] = GoldOre::class;;
|
||||
self::$list[self::IRON_ORE] = IronOre::class;;
|
||||
self::$list[self::COAL_ORE] = CoalOre::class;;
|
||||
self::$list[self::WOOD] = Wood::class;;
|
||||
self::$list[self::LEAVES] = Leaves::class;;
|
||||
self::$list[self::SPONGE] = Sponge::class;;
|
||||
self::$list[self::GLASS] = Glass::class;;
|
||||
self::$list[self::LAPIS_ORE] = LapisOre::class;;
|
||||
self::$list[self::LAPIS_BLOCK] = Lapis::class;;
|
||||
self::$list[self::SANDSTONE] = Sandstone::class;;
|
||||
self::$list[self::BED_BLOCK] = Bed::class;;
|
||||
self::$list[self::COBWEB] = Cobweb::class;;
|
||||
self::$list[self::TALL_GRASS] = TallGrass::class;;
|
||||
self::$list[self::DEAD_BUSH] = DeadBush::class;;
|
||||
self::$list[self::WOOL] = Wool::class;;
|
||||
self::$list[self::DANDELION] = Dandelion::class;;
|
||||
self::$list[self::POPPY] = CyanFlower::class;;
|
||||
self::$list[self::BROWN_MUSHROOM] = BrownMushroom::class;;
|
||||
self::$list[self::RED_MUSHROOM] = RedMushroom::class;;
|
||||
self::$list[self::GOLD_BLOCK] = Gold::class;;
|
||||
self::$list[self::IRON_BLOCK] = Iron::class;;
|
||||
self::$list[self::DOUBLE_SLAB] = DoubleSlab::class;;
|
||||
self::$list[self::SLAB] = Slab::class;;
|
||||
self::$list[self::BRICKS_BLOCK] = Bricks::class;;
|
||||
self::$list[self::TNT] = TNT::class;;
|
||||
self::$list[self::BOOKSHELF] = Bookshelf::class;;
|
||||
self::$list[self::MOSS_STONE] = MossStone::class;;
|
||||
self::$list[self::OBSIDIAN] = Obsidian::class;;
|
||||
self::$list[self::TORCH] = Torch::class;;
|
||||
self::$list[self::FIRE] = Fire::class;;
|
||||
self::$list[self::MONSTER_SPAWNER] = MonsterSpawner::class;;
|
||||
self::$list[self::WOOD_STAIRS] = WoodStairs::class;;
|
||||
self::$list[self::CHEST] = Chest::class;;
|
||||
|
||||
self::DIAMOND_ORE => DiamondOre::class,
|
||||
self::DIAMOND_BLOCK => Diamond::class,
|
||||
self::WORKBENCH => Workbench::class,
|
||||
self::WHEAT_BLOCK => Wheat::class,
|
||||
self::FARMLAND => Farmland::class,
|
||||
self::FURNACE => Furnace::class,
|
||||
self::BURNING_FURNACE => BurningFurnace::class,
|
||||
self::SIGN_POST => SignPost::class,
|
||||
self::WOOD_DOOR_BLOCK => WoodDoor::class,
|
||||
self::LADDER => Ladder::class,
|
||||
self::$list[self::DIAMOND_ORE] = DiamondOre::class;;
|
||||
self::$list[self::DIAMOND_BLOCK] = Diamond::class;;
|
||||
self::$list[self::WORKBENCH] = Workbench::class;;
|
||||
self::$list[self::WHEAT_BLOCK] = Wheat::class;;
|
||||
self::$list[self::FARMLAND] = Farmland::class;;
|
||||
self::$list[self::FURNACE] = Furnace::class;;
|
||||
self::$list[self::BURNING_FURNACE] = BurningFurnace::class;;
|
||||
self::$list[self::SIGN_POST] = SignPost::class;;
|
||||
self::$list[self::WOOD_DOOR_BLOCK] = WoodDoor::class;;
|
||||
self::$list[self::LADDER] = Ladder::class;;
|
||||
|
||||
self::COBBLESTONE_STAIRS => CobblestoneStairs::class,
|
||||
self::WALL_SIGN => WallSign::class,
|
||||
self::$list[self::COBBLESTONE_STAIRS] = CobblestoneStairs::class;;
|
||||
self::$list[self::WALL_SIGN] = WallSign::class;;
|
||||
|
||||
self::IRON_DOOR_BLOCK => IronDoor::class,
|
||||
self::REDSTONE_ORE => RedstoneOre::class,
|
||||
self::GLOWING_REDSTONE_ORE => GlowingRedstoneOre::class,
|
||||
self::$list[self::IRON_DOOR_BLOCK] = IronDoor::class;;
|
||||
self::$list[self::REDSTONE_ORE] = RedstoneOre::class;;
|
||||
self::$list[self::GLOWING_REDSTONE_ORE] = GlowingRedstoneOre::class;;
|
||||
|
||||
self::SNOW_LAYER => SnowLayer::class,
|
||||
self::ICE => Ice::class,
|
||||
self::SNOW_BLOCK => Snow::class,
|
||||
self::CACTUS => Cactus::class,
|
||||
self::CLAY_BLOCK => Clay::class,
|
||||
self::SUGARCANE_BLOCK => Sugarcane::class,
|
||||
self::$list[self::SNOW_LAYER] = SnowLayer::class;;
|
||||
self::$list[self::ICE] = Ice::class;;
|
||||
self::$list[self::SNOW_BLOCK] = Snow::class;;
|
||||
self::$list[self::CACTUS] = Cactus::class;;
|
||||
self::$list[self::CLAY_BLOCK] = Clay::class;;
|
||||
self::$list[self::SUGARCANE_BLOCK] = Sugarcane::class;;
|
||||
|
||||
self::FENCE => Fence::class,
|
||||
self::PUMPKIN => Pumpkin::class,
|
||||
self::NETHERRACK => Netherrack::class,
|
||||
self::SOUL_SAND => SoulSand::class,
|
||||
self::GLOWSTONE_BLOCK => Glowstone::class,
|
||||
self::$list[self::FENCE] = Fence::class;;
|
||||
self::$list[self::PUMPKIN] = Pumpkin::class;;
|
||||
self::$list[self::NETHERRACK] = Netherrack::class;;
|
||||
self::$list[self::SOUL_SAND] = SoulSand::class;;
|
||||
self::$list[self::GLOWSTONE_BLOCK] = Glowstone::class;;
|
||||
|
||||
self::LIT_PUMPKIN => LitPumpkin::class,
|
||||
self::CAKE_BLOCK => Cake::class,
|
||||
self::$list[self::LIT_PUMPKIN] = LitPumpkin::class;;
|
||||
self::$list[self::CAKE_BLOCK] = Cake::class;;
|
||||
|
||||
self::TRAPDOOR => Trapdoor::class,
|
||||
self::$list[self::TRAPDOOR] = Trapdoor::class;;
|
||||
|
||||
self::STONE_BRICKS => StoneBricks::class,
|
||||
self::$list[self::STONE_BRICKS] = StoneBricks::class;;
|
||||
|
||||
self::IRON_BARS => IronBars::class,
|
||||
self::GLASS_PANE => GlassPane::class,
|
||||
self::MELON_BLOCK => Melon::class,
|
||||
self::PUMPKIN_STEM => PumpkinStem::class,
|
||||
self::MELON_STEM => MelonStem::class,
|
||||
self::VINE => Vine::class,
|
||||
self::FENCE_GATE => FenceGate::class,
|
||||
self::BRICK_STAIRS => BrickStairs::class,
|
||||
self::STONE_BRICK_STAIRS => StoneBrickStairs::class,
|
||||
self::$list[self::IRON_BARS] = IronBars::class;;
|
||||
self::$list[self::GLASS_PANE] = GlassPane::class;;
|
||||
self::$list[self::MELON_BLOCK] = Melon::class;;
|
||||
self::$list[self::PUMPKIN_STEM] = PumpkinStem::class;;
|
||||
self::$list[self::MELON_STEM] = MelonStem::class;;
|
||||
self::$list[self::VINE] = Vine::class;;
|
||||
self::$list[self::FENCE_GATE] = FenceGate::class;;
|
||||
self::$list[self::BRICK_STAIRS] = BrickStairs::class;;
|
||||
self::$list[self::STONE_BRICK_STAIRS] = StoneBrickStairs::class;;
|
||||
|
||||
self::MYCELIUM => Mycelium::class,
|
||||
self::NETHER_BRICKS => NetherBrick::class,
|
||||
self::$list[self::MYCELIUM] = Mycelium::class;;
|
||||
self::$list[self::NETHER_BRICKS] = NetherBrick::class;;
|
||||
|
||||
self::NETHER_BRICKS_STAIRS => NetherBrickStairs::class,
|
||||
self::$list[self::NETHER_BRICKS_STAIRS] = NetherBrickStairs::class;;
|
||||
|
||||
self::END_PORTAL => EndPortal::class,
|
||||
self::END_STONE => EndStone::class,
|
||||
self::SANDSTONE_STAIRS => SandstoneStairs::class,
|
||||
self::EMERALD_ORE => EmeraldOre::class,
|
||||
self::$list[self::END_PORTAL] = EndPortal::class;;
|
||||
self::$list[self::END_STONE] = EndStone::class;;
|
||||
self::$list[self::SANDSTONE_STAIRS] = SandstoneStairs::class;;
|
||||
self::$list[self::EMERALD_ORE] = EmeraldOre::class;;
|
||||
|
||||
self::EMERALD_BLOCK => Emerald::class,
|
||||
self::SPRUCE_WOOD_STAIRS => SpruceWoodStairs::class,
|
||||
self::BIRCH_WOOD_STAIRS => BirchWoodStairs::class,
|
||||
self::JUNGLE_WOOD_STAIRS => JungleWoodStairs::class,
|
||||
self::STONE_WALL => StoneWall::class,
|
||||
self::$list[self::EMERALD_BLOCK] = Emerald::class;;
|
||||
self::$list[self::SPRUCE_WOOD_STAIRS] = SpruceWoodStairs::class;;
|
||||
self::$list[self::BIRCH_WOOD_STAIRS] = BirchWoodStairs::class;;
|
||||
self::$list[self::JUNGLE_WOOD_STAIRS] = JungleWoodStairs::class;;
|
||||
self::$list[self::STONE_WALL] = StoneWall::class;;
|
||||
|
||||
self::CARROT_BLOCK => Carrot::class,
|
||||
self::POTATO_BLOCK => Potato::class,
|
||||
self::$list[self::CARROT_BLOCK] = Carrot::class;;
|
||||
self::$list[self::POTATO_BLOCK] = Potato::class;;
|
||||
|
||||
self::QUARTZ_BLOCK => Quartz::class,
|
||||
self::QUARTZ_STAIRS => QuartzStairs::class,
|
||||
self::DOUBLE_WOOD_SLAB => DoubleWoodSlab::class,
|
||||
self::WOOD_SLAB => WoodSlab::class,
|
||||
self::STAINED_CLAY => StainedClay::class,
|
||||
self::$list[self::QUARTZ_BLOCK] = Quartz::class;;
|
||||
self::$list[self::QUARTZ_STAIRS] = QuartzStairs::class;;
|
||||
self::$list[self::DOUBLE_WOOD_SLAB] = DoubleWoodSlab::class;;
|
||||
self::$list[self::WOOD_SLAB] = WoodSlab::class;;
|
||||
self::$list[self::STAINED_CLAY] = StainedClay::class;;
|
||||
|
||||
self::LEAVES2 => Leaves2::class,
|
||||
self::WOOD2 => Wood2::class,
|
||||
self::ACACIA_WOOD_STAIRS => AcaciaWoodStairs::class,
|
||||
self::DARK_OAK_WOOD_STAIRS => DarkOakWoodStairs::class,
|
||||
self::$list[self::LEAVES2] = Leaves2::class;;
|
||||
self::$list[self::WOOD2] = Wood2::class;;
|
||||
self::$list[self::ACACIA_WOOD_STAIRS] = AcaciaWoodStairs::class;;
|
||||
self::$list[self::DARK_OAK_WOOD_STAIRS] = DarkOakWoodStairs::class;;
|
||||
|
||||
self::HAY_BALE => HayBale::class,
|
||||
self::CARPET => Carpet::class,
|
||||
self::HARDENED_CLAY => HardenedClay::class,
|
||||
self::COAL_BLOCK => Coal::class,
|
||||
self::$list[self::HAY_BALE] = HayBale::class;;
|
||||
self::$list[self::CARPET] = Carpet::class;;
|
||||
self::$list[self::HARDENED_CLAY] = HardenedClay::class;;
|
||||
self::$list[self::COAL_BLOCK] = Coal::class;;
|
||||
|
||||
self::PODZOL => Podzol::class,
|
||||
self::BEETROOT_BLOCK => Beetroot::class,
|
||||
self::STONECUTTER => Stonecutter::class,
|
||||
self::GLOWING_OBSIDIAN => GlowingObsidian::class,
|
||||
self::NETHER_REACTOR => NetherReactor::class,
|
||||
];
|
||||
self::$list[self::FENCE_GATE_SPRUCE] = FenceGateSpruce::class;
|
||||
self::$list[self::FENCE_GATE_BIRCH] = FenceGateBirch::class;
|
||||
self::$list[self::FENCE_GATE_JUNGLE] = FenceGateJungle::class;
|
||||
self::$list[self::FENCE_GATE_DARK_OAK] = FenceGateDarkOak::class;
|
||||
self::$list[self::FENCE_GATE_ACACIA] = FenceGateAcacia::class;
|
||||
self::$list[self::FENCE_SPRUCE] = FenceSpruce::class;
|
||||
self::$list[self::FENCE_BIRCH] = FenceBirch::class;
|
||||
self::$list[self::FENCE_DARK_OAK] = FenceDarkOak::class;
|
||||
self::$list[self::FENCE_JUNGLE] = FenceJungle::class;
|
||||
self::$list[self::FENCE_ACACIA] = FenceAcacia::class;
|
||||
|
||||
self::$list[self::PODZOL] = Podzol::class;;
|
||||
self::$list[self::BEETROOT_BLOCK] = Beetroot::class;;
|
||||
self::$list[self::STONECUTTER] = Stonecutter::class;;
|
||||
self::$list[self::GLOWING_OBSIDIAN] = GlowingObsidian::class;;
|
||||
self::$list[self::NETHER_REACTOR] = NetherReactor::class;;
|
||||
}
|
||||
}
|
||||
|
||||
@ -680,14 +713,18 @@ class Block extends Position implements Metadatable{
|
||||
* @return Block
|
||||
*/
|
||||
public static function get($id, $meta = 0, Position $pos = null){
|
||||
if(isset(self::$list[$id])){
|
||||
try{
|
||||
$block = self::$list[$id];
|
||||
$block = new $block($meta);
|
||||
}else{
|
||||
if($block !== null){
|
||||
$block = new $block($meta);
|
||||
}else{
|
||||
$block = new Block($id, $meta);
|
||||
}
|
||||
}catch(\RuntimeException $e){
|
||||
$block = new Block($id, $meta);
|
||||
}
|
||||
|
||||
if($pos instanceof Position){
|
||||
if($pos !== null){
|
||||
$block->x = $pos->x;
|
||||
$block->y = $pos->y;
|
||||
$block->z = $pos->z;
|
||||
@ -788,7 +825,7 @@ class Block extends Position implements Metadatable{
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
final public function getID(){
|
||||
final public function getId(){
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
@ -820,7 +857,6 @@ class Block extends Position implements Metadatable{
|
||||
$this->y = (int) $v->y;
|
||||
$this->z = (int) $v->z;
|
||||
$this->level = $v->level;
|
||||
$this->boundingBox = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -901,9 +937,16 @@ class Block extends Position implements Metadatable{
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}else{
|
||||
return $this->boundingBox = $this->recalculateBoundingBox();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
/**
|
||||
* @return AxisAlignedBB
|
||||
*/
|
||||
protected function recalculateBoundingBox(){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
|
@ -55,7 +55,7 @@ class BurningFurnace extends Solid{
|
||||
new Int("z", $this->z)
|
||||
]);
|
||||
$nbt->Items->setTagType(NBT::TAG_Compound);
|
||||
new Furnace($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
Tile::createTile("Furnace", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -81,7 +81,7 @@ class BurningFurnace extends Solid{
|
||||
new Int("z", $this->z)
|
||||
]);
|
||||
$nbt->Items->setTagType(NBT::TAG_Compound);
|
||||
$furnace = new Furnace($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
$furnace = Tile::createTile("Furnace", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
}
|
||||
|
||||
if(($player->getGamemode() & 0x01) === 0x01){
|
||||
|
@ -28,7 +28,7 @@ use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
|
||||
@ -42,12 +42,9 @@ class Cactus extends Transparent{
|
||||
$this->hardness = 2;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 0.0625,
|
||||
$this->y,
|
||||
$this->z + 0.0625,
|
||||
@ -59,10 +56,7 @@ class Cactus extends Transparent{
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
||||
if(!$ev->isCancelled()){
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
|
@ -37,14 +37,11 @@ class Cake extends Transparent{
|
||||
$this->hardness = 2.5;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
$f = (1 + $this->getDamage() * 2) / 16;
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $f,
|
||||
$this->y,
|
||||
$this->z + 0.0625,
|
||||
|
@ -53,12 +53,9 @@ class Carpet extends Flowable{
|
||||
$this->isSolid = true;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
|
@ -42,12 +42,9 @@ class Chest extends Transparent{
|
||||
$this->hardness = 15;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 0.0625,
|
||||
$this->y,
|
||||
$this->z + 0.0625,
|
||||
@ -65,7 +62,7 @@ class Chest extends Transparent{
|
||||
3 => 3,
|
||||
];
|
||||
|
||||
$chest = false;
|
||||
$chest = null;
|
||||
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
|
||||
|
||||
for($side = 2; $side <= 5; ++$side){
|
||||
@ -93,9 +90,9 @@ class Chest extends Transparent{
|
||||
new Int("z", $this->z)
|
||||
]);
|
||||
$nbt->Items->setTagType(NBT::TAG_Compound);
|
||||
$tile = new TileChest($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
$tile = Tile::createTile("Chest", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
|
||||
if($chest instanceof TileChest){
|
||||
if($chest instanceof TileChest and $tile instanceof TileChest){
|
||||
$chest->pairWith($tile);
|
||||
$tile->pairWith($chest);
|
||||
}
|
||||
@ -133,11 +130,11 @@ class Chest extends Transparent{
|
||||
new Int("z", $this->z)
|
||||
]);
|
||||
$nbt->Items->setTagType(NBT::TAG_Compound);
|
||||
$chest = new TileChest($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
$chest = Tile::createTile("Chest", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
}
|
||||
|
||||
|
||||
if(($player->gamemode & 0x01) === 0x01){
|
||||
if($player->isCreative()){
|
||||
return true;
|
||||
}
|
||||
$player->addWindow($chest->getInventory());
|
||||
|
@ -52,10 +52,7 @@ abstract class Door extends Transparent{
|
||||
return $first & 0x07 | ($flag ? 8 : 0) | ($flag1 ? 0x10 : 0);
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
$f = 0.1875;
|
||||
$damage = $this->getFullDamage();
|
||||
@ -76,7 +73,7 @@ abstract class Door extends Transparent{
|
||||
if($j === 0){
|
||||
if($flag){
|
||||
if(!$flag1){
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -85,7 +82,7 @@ abstract class Door extends Transparent{
|
||||
$this->z + $f
|
||||
);
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 1 - $f,
|
||||
@ -95,7 +92,7 @@ abstract class Door extends Transparent{
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -107,7 +104,7 @@ abstract class Door extends Transparent{
|
||||
}elseif($j === 1){
|
||||
if($flag){
|
||||
if(!$flag1){
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x + 1 - $f,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -116,7 +113,7 @@ abstract class Door extends Transparent{
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -126,7 +123,7 @@ abstract class Door extends Transparent{
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -138,7 +135,7 @@ abstract class Door extends Transparent{
|
||||
}elseif($j === 2){
|
||||
if($flag){
|
||||
if(!$flag1){
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 1 - $f,
|
||||
@ -147,7 +144,7 @@ abstract class Door extends Transparent{
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -157,7 +154,7 @@ abstract class Door extends Transparent{
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x + 1 - $f,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -169,7 +166,7 @@ abstract class Door extends Transparent{
|
||||
}elseif($j === 3){
|
||||
if($flag){
|
||||
if(!$flag1){
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -178,7 +175,7 @@ abstract class Door extends Transparent{
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x + 1 - $f,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -188,7 +185,7 @@ abstract class Door extends Transparent{
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 1 - $f,
|
||||
@ -199,7 +196,7 @@ abstract class Door extends Transparent{
|
||||
}
|
||||
}
|
||||
|
||||
return $this->boundingBox = $bb;
|
||||
return $bb;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
@ -274,7 +271,7 @@ abstract class Door extends Transparent{
|
||||
if($player instanceof Player){
|
||||
unset($players[$player->getID()]);
|
||||
}
|
||||
$pk = new LevelEventPacket;
|
||||
$pk = new LevelEventPacket();
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
$pk->z = $this->z;
|
||||
@ -293,7 +290,7 @@ abstract class Door extends Transparent{
|
||||
if($player instanceof Player){
|
||||
unset($players[$player->getID()]);
|
||||
}
|
||||
$pk = new LevelEventPacket;
|
||||
$pk = new LevelEventPacket();
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
$pk->z = $this->z;
|
||||
|
@ -29,12 +29,9 @@ class EndPortal extends Solid{
|
||||
$this->hardness = 18000000;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\FallingBlock;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
@ -29,6 +29,7 @@ use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Double;
|
||||
use pocketmine\nbt\tag\Enum;
|
||||
use pocketmine\nbt\tag\Float;
|
||||
use pocketmine\nbt\tag\Int;
|
||||
use pocketmine\Player;
|
||||
|
||||
abstract class Fallable extends Solid{
|
||||
@ -45,7 +46,7 @@ abstract class Fallable extends Solid{
|
||||
if($this->hasPhysics === true and $type === Level::BLOCK_UPDATE_NORMAL){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === self::AIR or ($down instanceof Liquid)){
|
||||
$fall = new FallingBlock($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", [
|
||||
new Double("", $this->x + 0.5),
|
||||
new Double("", $this->y),
|
||||
@ -60,13 +61,12 @@ abstract class Fallable extends Solid{
|
||||
new Float("", 0),
|
||||
new Float("", 0)
|
||||
]),
|
||||
"Tile" => new Byte("Tile", $this->getID())
|
||||
"TileID" => new Int("TileID", $this->getID()),
|
||||
"Data" => new Byte("Data", $this->getDamage()),
|
||||
]));
|
||||
|
||||
$fall->spawnToAll();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -30,12 +30,9 @@ class Farmland extends Solid{
|
||||
$this->hardness = 3;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
|
@ -21,20 +21,16 @@
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
class Fence extends Transparent{
|
||||
public function __construct(){
|
||||
parent::__construct(self::FENCE, 0, "Fence");
|
||||
parent::__construct(self::FENCE, 0, "Oak Fence");
|
||||
$this->isFullBlock = false;
|
||||
$this->hardness = 15;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
$flag = $this->canConnect($this->getSide(2));
|
||||
$flag1 = $this->canConnect($this->getSide(3));
|
||||
@ -46,18 +42,18 @@ class Fence extends Transparent{
|
||||
$f2 = $flag ? 0 : 0.375;
|
||||
$f3 = $flag1 ? 1 : 0.625;
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $f,
|
||||
$this->y,
|
||||
$this->z + $f2,
|
||||
$this->x + $f1,
|
||||
$this->y + 1, //TODO: check this, add extra bounding box
|
||||
$this->y + 1,
|
||||
$this->z + $f3
|
||||
);
|
||||
}
|
||||
|
||||
public function canConnect(Block $block){
|
||||
return ($block->getID() !== self::FENCE and $block->getID() !== self::FENCE_GATE) ? $block->isSolid : true;
|
||||
return (!($block instanceof Fence) and !($block instanceof FenceGate)) ? $block->isSolid : true;
|
||||
}
|
||||
|
||||
}
|
30
src/pocketmine/block/FenceAcacia.php
Normal file
30
src/pocketmine/block/FenceAcacia.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class FenceAcacia extends Fence{
|
||||
public function __construct(){
|
||||
Transparent::__construct(self::FENCE_ACACIA, 0, "Acacia Fence");
|
||||
$this->isFullBlock = false;
|
||||
$this->hardness = 15;
|
||||
}
|
||||
}
|
30
src/pocketmine/block/FenceBirch.php
Normal file
30
src/pocketmine/block/FenceBirch.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class FenceBirch extends Fence{
|
||||
public function __construct(){
|
||||
Transparent::__construct(self::FENCE_BIRCH, 0, "Birch Fence");
|
||||
$this->isFullBlock = false;
|
||||
$this->hardness = 15;
|
||||
}
|
||||
}
|
30
src/pocketmine/block/FenceDarkOak.php
Normal file
30
src/pocketmine/block/FenceDarkOak.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class FenceDarkOak extends Fence{
|
||||
public function __construct(){
|
||||
Transparent::__construct(self::FENCE_DARK_OAK, 0, "Dark Oak Fence");
|
||||
$this->isFullBlock = false;
|
||||
$this->hardness = 15;
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ use pocketmine\Player;
|
||||
|
||||
class FenceGate extends Transparent{
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::FENCE_GATE, $meta, "Fence Gate");
|
||||
parent::__construct(self::FENCE_GATE, $meta, "Oak Fence Gate");
|
||||
$this->isActivable = true;
|
||||
if(($this->meta & 0x04) === 0x04){
|
||||
$this->isFullBlock = true;
|
||||
@ -38,10 +38,7 @@ class FenceGate extends Transparent{
|
||||
}
|
||||
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
if(($this->getDamage() & 0x04) > 0){
|
||||
return null;
|
||||
@ -49,7 +46,7 @@ class FenceGate extends Transparent{
|
||||
|
||||
$i = ($this->getDamage() & 0x03);
|
||||
if($i === 2 and $i === 0){
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 0.375,
|
||||
@ -58,7 +55,7 @@ class FenceGate extends Transparent{
|
||||
$this->z + 0.625
|
||||
);
|
||||
}else{
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 0.375,
|
||||
$this->y,
|
||||
$this->z,
|
||||
|
36
src/pocketmine/block/FenceGateAcacia.php
Normal file
36
src/pocketmine/block/FenceGateAcacia.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class FenceGateAcacia extends FenceGate{
|
||||
public function __construct($meta = 0){
|
||||
Transparent::__construct(self::FENCE_GATE_ACACIA, $meta, "Acacia Fence Gate");
|
||||
$this->isActivable = true;
|
||||
if(($this->meta & 0x04) === 0x04){
|
||||
$this->isFullBlock = true;
|
||||
}else{
|
||||
$this->isFullBlock = false;
|
||||
}
|
||||
$this->hardness = 15;
|
||||
}
|
||||
}
|
36
src/pocketmine/block/FenceGateBirch.php
Normal file
36
src/pocketmine/block/FenceGateBirch.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class FenceGateBirch extends FenceGate{
|
||||
public function __construct($meta = 0){
|
||||
Transparent::__construct(self::FENCE_GATE_BIRCH, $meta, "Birch Fence Gate");
|
||||
$this->isActivable = true;
|
||||
if(($this->meta & 0x04) === 0x04){
|
||||
$this->isFullBlock = true;
|
||||
}else{
|
||||
$this->isFullBlock = false;
|
||||
}
|
||||
$this->hardness = 15;
|
||||
}
|
||||
}
|
36
src/pocketmine/block/FenceGateDarkOak.php
Normal file
36
src/pocketmine/block/FenceGateDarkOak.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class FenceGateDarkOak extends FenceGate{
|
||||
public function __construct($meta = 0){
|
||||
Transparent::__construct(self::FENCE_GATE_DARK_OAK, $meta, "Dark Oak Fence Gate");
|
||||
$this->isActivable = true;
|
||||
if(($this->meta & 0x04) === 0x04){
|
||||
$this->isFullBlock = true;
|
||||
}else{
|
||||
$this->isFullBlock = false;
|
||||
}
|
||||
$this->hardness = 15;
|
||||
}
|
||||
}
|
36
src/pocketmine/block/FenceGateJungle.php
Normal file
36
src/pocketmine/block/FenceGateJungle.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class FenceGateJungle extends FenceGate{
|
||||
public function __construct($meta = 0){
|
||||
Transparent::__construct(self::FENCE_GATE_JUNGLE, $meta, "Jungle Fence Gate");
|
||||
$this->isActivable = true;
|
||||
if(($this->meta & 0x04) === 0x04){
|
||||
$this->isFullBlock = true;
|
||||
}else{
|
||||
$this->isFullBlock = false;
|
||||
}
|
||||
$this->hardness = 15;
|
||||
}
|
||||
}
|
36
src/pocketmine/block/FenceGateSpruce.php
Normal file
36
src/pocketmine/block/FenceGateSpruce.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class FenceGateSpruce extends FenceGate{
|
||||
public function __construct($meta = 0){
|
||||
Transparent::__construct(self::FENCE_GATE_SPRUCE, $meta, "Spruce Fence Gate");
|
||||
$this->isActivable = true;
|
||||
if(($this->meta & 0x04) === 0x04){
|
||||
$this->isFullBlock = true;
|
||||
}else{
|
||||
$this->isFullBlock = false;
|
||||
}
|
||||
$this->hardness = 15;
|
||||
}
|
||||
}
|
30
src/pocketmine/block/FenceJungle.php
Normal file
30
src/pocketmine/block/FenceJungle.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class FenceJungle extends Fence{
|
||||
public function __construct(){
|
||||
Transparent::__construct(self::FENCE_JUNGLE, 0, "Jungle Fence");
|
||||
$this->isFullBlock = false;
|
||||
$this->hardness = 15;
|
||||
}
|
||||
}
|
30
src/pocketmine/block/FenceSpruce.php
Normal file
30
src/pocketmine/block/FenceSpruce.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class FenceSpruce extends Fence{
|
||||
public function __construct(){
|
||||
Transparent::__construct(self::FENCE_SPRUCE, 0, "Spruce Fence");
|
||||
$this->isFullBlock = false;
|
||||
$this->hardness = 15;
|
||||
}
|
||||
}
|
@ -47,10 +47,7 @@ class Fire extends Flowable{
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
||||
if(!$ev->isCancelled()){
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
|
||||
$ev = new EntityCombustByBlockEvent($this, $entity, 8);
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
||||
|
@ -25,7 +25,7 @@ use pocketmine\event\block\BlockSpreadEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\generator\object\TallGrass as TallGrassObject;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\Random;
|
||||
@ -54,9 +54,8 @@ class Grass extends Solid{
|
||||
$x = mt_rand($this->x - 1, $this->x + 1);
|
||||
$y = mt_rand($this->y - 2, $this->y + 2);
|
||||
$z = mt_rand($this->z - 1, $this->z + 1);
|
||||
$block = $this->getLevel()->getBlockIdAt($x, $y, $z);
|
||||
if($block === Block::DIRT){
|
||||
$block = Block::get($block, $this->getLevel()->getBlockDataAt($x, $y, $z), new Position($x, $y, $z, $this->getLevel()));
|
||||
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
|
||||
if($block->getID() === Block::DIRT){
|
||||
if($block->getSide(1) instanceof Transparent){
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($block, $this, new Grass()));
|
||||
if(!$ev->isCancelled()){
|
||||
|
@ -43,15 +43,12 @@ class Ladder extends Transparent{
|
||||
$entity->onGround = true;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
$f = 0.125;
|
||||
|
||||
if($this->meta === 2){
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 1 - $f,
|
||||
@ -60,7 +57,7 @@ class Ladder extends Transparent{
|
||||
$this->z + 1
|
||||
);
|
||||
}elseif($this->meta === 3){
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -69,7 +66,7 @@ class Ladder extends Transparent{
|
||||
$this->z + $f
|
||||
);
|
||||
}elseif($this->meta === 4){
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 1 - $f,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -78,7 +75,7 @@ class Ladder extends Transparent{
|
||||
$this->z + 1
|
||||
);
|
||||
}elseif($this->meta === 5){
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
|
@ -39,16 +39,17 @@ class Lava extends Liquid{
|
||||
public function onEntityCollide(Entity $entity){
|
||||
$entity->fallDistance *= 0.5;
|
||||
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_LAVA, 4);
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
||||
if(!$ev->isCancelled()){
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
|
||||
$ev = new EntityCombustByBlockEvent($this, $entity, 15);
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
||||
if(!$ev->isCancelled()){
|
||||
$entity->setOnFire($ev->getDuration());
|
||||
}
|
||||
|
||||
if($entity instanceof Player){
|
||||
$entity->onGround = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
|
@ -24,7 +24,7 @@ namespace pocketmine\block;
|
||||
use pocketmine\event\block\BlockSpreadEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Server;
|
||||
|
||||
class Mycelium extends Solid{
|
||||
@ -45,9 +45,8 @@ class Mycelium extends Solid{
|
||||
$x = mt_rand($this->x - 1, $this->x + 1);
|
||||
$y = mt_rand($this->y - 2, $this->y + 2);
|
||||
$z = mt_rand($this->z - 1, $this->z + 1);
|
||||
$block = $this->getLevel()->getBlockIdAt($x, $y, $z);
|
||||
if($block === Block::DIRT){
|
||||
$block = Block::get($block, $this->getLevel()->getBlockDataAt($x, $y, $z), new Position($x, $y, $z, $this->getLevel()));
|
||||
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
|
||||
if($block->getID() === Block::DIRT){
|
||||
if($block->getSide(1) instanceof Transparent){
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($block, $this, new Mycelium()));
|
||||
if(!$ev->isCancelled()){
|
||||
|
@ -47,13 +47,10 @@ class Slab extends Transparent{
|
||||
$this->hardness = 30;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
if(($this->meta & 0x08) > 0){
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y + 0.5,
|
||||
$this->z,
|
||||
@ -62,7 +59,7 @@ class Slab extends Transparent{
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
|
@ -30,12 +30,9 @@ class SoulSand extends Solid{
|
||||
$this->hardness = 2.5;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
|
@ -54,7 +54,7 @@ abstract class Stair extends Transparent{
|
||||
$f3 = 0.5;
|
||||
}
|
||||
|
||||
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
|
||||
if($bb->intersectsWith($bb2 = AxisAlignedBB::getBoundingBoxFromPool(
|
||||
$this->x,
|
||||
$this->y + $f,
|
||||
$this->z,
|
||||
@ -66,7 +66,7 @@ abstract class Stair extends Transparent{
|
||||
}
|
||||
|
||||
if($j === 0){
|
||||
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
|
||||
if($bb->intersectsWith($bb2 = AxisAlignedBB::getBoundingBoxFromPool(
|
||||
$this->x + 0.5,
|
||||
$this->y + $f2,
|
||||
$this->z,
|
||||
@ -77,7 +77,7 @@ abstract class Stair extends Transparent{
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}elseif($j === 1){
|
||||
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
|
||||
if($bb->intersectsWith($bb2 = AxisAlignedBB::getBoundingBoxFromPool(
|
||||
$this->x,
|
||||
$this->y + $f2,
|
||||
$this->z,
|
||||
@ -88,7 +88,7 @@ abstract class Stair extends Transparent{
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}elseif($j === 2){
|
||||
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
|
||||
if($bb->intersectsWith($bb2 = AxisAlignedBB::getBoundingBoxFromPool(
|
||||
$this->x,
|
||||
$this->y + $f2,
|
||||
$this->z + 0.5,
|
||||
@ -99,7 +99,7 @@ abstract class Stair extends Transparent{
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}elseif($j === 3){
|
||||
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
|
||||
if($bb->intersectsWith($bb2 = AxisAlignedBB::getBoundingBoxFromPool(
|
||||
$this->x,
|
||||
$this->y + $f2,
|
||||
$this->z,
|
||||
@ -113,13 +113,10 @@ abstract class Stair extends Transparent{
|
||||
}
|
||||
*/
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
if(($this->getDamage() & 0x04) > 0){
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y + 0.5,
|
||||
$this->z,
|
||||
@ -128,7 +125,7 @@ abstract class Stair extends Transparent{
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
|
@ -22,6 +22,7 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
|
||||
class Stone extends Solid{
|
||||
const NORMAL = 0;
|
||||
@ -45,6 +46,7 @@ class Stone extends Solid{
|
||||
self::POLISHED_DIORITE => "Polished Diorite",
|
||||
self::ANDESITE => "Andesite",
|
||||
self::POLISHED_ANDESITE => "Polished Andesite",
|
||||
7 => "Unknown Stone",
|
||||
];
|
||||
$this->name = $names[$this->meta & 0x07];
|
||||
}
|
||||
@ -67,7 +69,7 @@ class Stone extends Solid{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
if($item->isPickaxe() >= Tool::TIER_WOODEN){
|
||||
return [
|
||||
[Item::COBBLESTONE, 0, 1],
|
||||
];
|
||||
|
@ -36,10 +36,7 @@ class StoneWall extends Transparent{
|
||||
$this->hardness = 30;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
$flag = $this->canConnect($this->getSide(2));
|
||||
$flag1 = $this->canConnect($this->getSide(3));
|
||||
@ -62,7 +59,7 @@ class StoneWall extends Transparent{
|
||||
$f3 = 0.6875;
|
||||
}
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $f,
|
||||
$this->y,
|
||||
$this->z + $f2,
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\PrimedTNT;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
@ -41,10 +41,10 @@ class TNT extends Solid{
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
if($item->getID() === Item::FLINT_STEEL){
|
||||
$item->useOn($this);
|
||||
$this->getLevel()->setBlock($this, new Air(), false, false, true);
|
||||
$this->getLevel()->setBlock($this, new Air(), true);
|
||||
|
||||
$mot = (new Random())->nextSignedFloat() * M_PI * 2;
|
||||
$tnt = new PrimedTNT($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new Compound("", [
|
||||
$tnt = Entity::createEntity("PrimedTNT", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new Compound("", [
|
||||
"Pos" => new Enum("Pos", [
|
||||
new Double("", $this->x + 0.5),
|
||||
new Double("", $this->y),
|
||||
|
@ -29,10 +29,7 @@ abstract class Thin extends Transparent{
|
||||
public $isFullBlock = false;
|
||||
public $isSolid = false;
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
$f = 0.4375;
|
||||
$f1 = 0.5625;
|
||||
@ -66,7 +63,7 @@ abstract class Thin extends Transparent{
|
||||
$f3 = 1;
|
||||
}
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $f,
|
||||
$this->y,
|
||||
$this->z + $f2,
|
||||
|
@ -37,17 +37,12 @@ class Trapdoor extends Transparent{
|
||||
$this->hardness = 15;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
$damage = $this->getDamage();
|
||||
|
||||
$f = 0.1875;
|
||||
|
||||
$bb = null;
|
||||
|
||||
if(($damage & 0x08) > 0){
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x,
|
||||
@ -70,7 +65,7 @@ class Trapdoor extends Transparent{
|
||||
|
||||
if(($damage & 0x04) > 0){
|
||||
if(($damage & 0x03) === 0){
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 1 - $f,
|
||||
@ -79,7 +74,7 @@ class Trapdoor extends Transparent{
|
||||
$this->z + 1
|
||||
);
|
||||
}elseif(($damage & 0x03) === 1){
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -88,7 +83,7 @@ class Trapdoor extends Transparent{
|
||||
$this->z + $f
|
||||
);
|
||||
}if(($damage & 0x03) === 2){
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x + 1 - $f,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -97,7 +92,7 @@ class Trapdoor extends Transparent{
|
||||
$this->z + 1
|
||||
);
|
||||
}if(($damage & 0x03) === 3){
|
||||
$bb = new AxisAlignedBB(
|
||||
$bb->setBounds(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -108,7 +103,7 @@ class Trapdoor extends Transparent{
|
||||
}
|
||||
}
|
||||
|
||||
return $this->boundingBox = $bb;
|
||||
return $bb;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
|
@ -43,10 +43,7 @@ class Vine extends Transparent{
|
||||
$entity->fallDistance = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
$f1 = 1;
|
||||
$f2 = 1;
|
||||
@ -96,7 +93,7 @@ class Vine extends Transparent{
|
||||
$f6 = 1;
|
||||
}
|
||||
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $f1,
|
||||
$this->y + $f2,
|
||||
$this->z + $f3,
|
||||
|
@ -36,6 +36,10 @@ class Water extends Liquid{
|
||||
if($entity->fireTicks > 0){
|
||||
$entity->extinguish();
|
||||
}
|
||||
|
||||
if($entity instanceof Player){
|
||||
$entity->onGround = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
|
@ -22,8 +22,6 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Wheat extends Crops{
|
||||
public function __construct($meta = 0){
|
||||
|
@ -23,14 +23,18 @@ namespace pocketmine\block;
|
||||
|
||||
|
||||
class Wood2 extends Wood{
|
||||
|
||||
const ACACIA = 0;
|
||||
const DARK_OAK = 1;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
Solid::__construct(self::WOOD2, $meta, "Wood");
|
||||
$names = [
|
||||
0 => "Acacia Wood",
|
||||
1 => "Dark Oak Wood"
|
||||
1 => "Dark Oak Wood",
|
||||
2 => ""
|
||||
];
|
||||
$this->name = $names[$this->meta & 0x03];
|
||||
$this->hardness = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,13 +45,10 @@ class WoodSlab extends Transparent{
|
||||
$this->hardness = 15;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if($this->boundingBox !== null){
|
||||
return $this->boundingBox;
|
||||
}
|
||||
protected function recalculateBoundingBox(){
|
||||
|
||||
if(($this->meta & 0x08) > 0){
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y + 0.5,
|
||||
$this->z,
|
||||
@ -60,7 +57,7 @@ class WoodSlab extends Transparent{
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
return $this->boundingBox = new AxisAlignedBB(
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
|
@ -181,7 +181,7 @@ class SimpleCommandMap implements CommandMap{
|
||||
try{
|
||||
$target->execute($sender, $sentCommandLabel, $args);
|
||||
}catch(\Exception $e){
|
||||
$this->server->getLogger()->critical("Unhandled exception executing command '". $commandLine ,"' in ". $target);
|
||||
$this->server->getLogger()->critical("Unhandled exception executing command '". $commandLine ."' in ". $target.": ".$e->getMessage());
|
||||
}
|
||||
$target->timings->stopTiming();
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\network\protocol\SetDifficultyPacket;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\TextFormat;
|
||||
|
||||
@ -55,6 +56,9 @@ class DifficultyCommand extends VanillaCommand{
|
||||
|
||||
if($difficulty !== -1){
|
||||
$sender->getServer()->setConfigInt("difficulty", $difficulty);
|
||||
$pk = new SetDifficultyPacket();
|
||||
$pk->difficulty = $sender->getServer()->getDifficulty();
|
||||
Server::broadcastPacket($sender->getServer()->getOnlinePlayers(), $pk);
|
||||
$sender->sendMessage("Set difficulty to " . $difficulty);
|
||||
}else{
|
||||
$sender->sendMessage("Unknown difficulty");
|
||||
|
@ -24,7 +24,6 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\TextFormat;
|
||||
|
||||
class KillCommand extends VanillaCommand{
|
||||
|
@ -46,7 +46,7 @@ class SetWorldSpawnCommand extends VanillaCommand{
|
||||
if(count($args) === 0){
|
||||
if($sender instanceof Player){
|
||||
$level = $sender->getLevel();
|
||||
$pos = $sender->round();
|
||||
$pos = (new Vector3($sender->x, $sender->y, $sender->z))->round();
|
||||
}else{
|
||||
$sender->sendMessage(TextFormat::RED . "You can only perform this command as a player");
|
||||
|
||||
|
@ -23,7 +23,6 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -88,8 +87,7 @@ class TeleportCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
if(count($args) < 3){
|
||||
$pos = new Position($target->x, $target->y, $target->z, $target->getLevel());
|
||||
$origin->teleport($pos);
|
||||
$origin->teleport($target);
|
||||
Command::broadcastCommandMessage($sender, "Teleported " . $origin->getDisplayName() . " to " . $target->getDisplayName());
|
||||
|
||||
return true;
|
||||
|
@ -32,12 +32,47 @@ class TimeCommand extends VanillaCommand{
|
||||
parent::__construct(
|
||||
$name,
|
||||
"Changes the time on each world",
|
||||
"/time set <value>\n/time add <value>"
|
||||
"/time set <value>\n/time add <value>\n/time start|stop"
|
||||
);
|
||||
$this->setPermission("pocketmine.command.time.add;pocketmine.command.time.set");
|
||||
$this->setPermission("pocketmine.command.time.add;pocketmine.command.time.set;pocketmine.command.time.start;pocketmine.command.time.stop");
|
||||
}
|
||||
|
||||
public function execute(CommandSender $sender, $currentAlias, array $args){
|
||||
if(count($args) < 1){
|
||||
$sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if($args[0] === "start"){
|
||||
if(!$sender->hasPermission("pocketmine.command.time.start")){
|
||||
$sender->sendMessage(TextFormat::RED . "You don't have permission to restart the time");
|
||||
|
||||
return true;
|
||||
}
|
||||
foreach($sender->getServer()->getLevels() as $level){
|
||||
$level->checkTime();
|
||||
$level->startTime();
|
||||
$level->checkTime();
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, "Restarted the time");
|
||||
return true;
|
||||
}elseif($args[0] === "stop"){
|
||||
if(!$sender->hasPermission("pocketmine.command.time.stop")){
|
||||
$sender->sendMessage(TextFormat::RED . "You don't have permission to stop the time");
|
||||
|
||||
return true;
|
||||
}
|
||||
foreach($sender->getServer()->getLevels() as $level){
|
||||
$level->checkTime();
|
||||
$level->stopTime();
|
||||
$level->checkTime();
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, "Stopped the time");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if(count($args) < 2){
|
||||
$sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage);
|
||||
|
||||
@ -78,6 +113,7 @@ class TimeCommand extends VanillaCommand{
|
||||
$level->setTime($level->getTime() + $value);
|
||||
$level->checkTime();
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, "Added " . $value ." to time");
|
||||
}else{
|
||||
$sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage);
|
||||
}
|
||||
|
@ -93,40 +93,39 @@ class TimingsCommand extends VanillaCommand{
|
||||
if($paste){
|
||||
fseek($fileTimings, 0);
|
||||
$data = [
|
||||
"public" => false,
|
||||
"description" => $sender->getServer()->getName() . " Timings",
|
||||
"files" => [
|
||||
"timings.txt" => [
|
||||
"content" => stream_get_contents($fileTimings)
|
||||
]
|
||||
]
|
||||
"syntax" => "text",
|
||||
"poster" => $sender->getServer()->getName(),
|
||||
"content" => stream_get_contents($fileTimings)
|
||||
];
|
||||
|
||||
$ch = curl_init("https://api.github.com/gists");
|
||||
$ch = curl_init("http://paste.ubuntu.com/");
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
|
||||
curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data, JSON_UNESCAPED_SLASHES));
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json", "User-Agent: " . $this->getName() . " " . $sender->getServer()->getPocketMineVersion()]);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
curl_setopt($ch, CURLOPT_AUTOREFERER, false);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
|
||||
curl_setopt($ch, CURLOPT_HEADER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ["User-Agent: " . $this->getName() . " " . $sender->getServer()->getPocketMineVersion()]);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$ret = curl_exec($ch);
|
||||
$data = json_decode($ret);
|
||||
$data = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
if($data === false or $data === null or !isset($data->html_url)){
|
||||
if(preg_match('#^Location: http://paste\\.ubuntu\\.com/([0-9]{1,})/#m', $data, $matches) == 0){
|
||||
$sender->sendMessage("An error happened while pasting the report");
|
||||
|
||||
return true;
|
||||
}
|
||||
$timings = $data->html_url;
|
||||
}
|
||||
|
||||
fclose($fileTimings);
|
||||
$sender->sendMessage("Timings written to " . $timings);
|
||||
$sender->sendMessage("Paste contents of file into form at http://aikar.co/timings.php to read results.");
|
||||
|
||||
$sender->sendMessage("Timings uploaded to http://paste.ubuntu.com/".$matches[1]."/");
|
||||
$sender->sendMessage("You can read the results at http://timings.aikar.co/?url=".$matches[1]);
|
||||
fclose($fileTimings);
|
||||
}else{
|
||||
fclose($fileTimings);
|
||||
$sender->sendMessage("Timings written to " . $timings);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -21,18 +21,8 @@
|
||||
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\event\entity\EntityCombustByEntityEvent;
|
||||
use pocketmine\event\entity\EntityDamageByEntityEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\event\entity\EntityRegainHealthEvent;
|
||||
use pocketmine\event\entity\ProjectileHitEvent;
|
||||
use pocketmine\level\format\FullChunk;
|
||||
use pocketmine\level\MovingObjectPosition;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Short;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\network\protocol\AddEntityPacket;
|
||||
use pocketmine\network\protocol\SetEntityMotionPacket;
|
||||
use pocketmine\Player;
|
||||
@ -44,29 +34,16 @@ class Arrow extends Projectile{
|
||||
public $length = 0.5;
|
||||
public $height = 0.5;
|
||||
|
||||
/** @var Entity */
|
||||
public $shootingEntity = null;
|
||||
|
||||
protected $gravity = 0.05;
|
||||
protected $drag = 0.01;
|
||||
|
||||
private $damage = 6;
|
||||
protected $damage = 6;
|
||||
|
||||
public function __construct(FullChunk $chunk, Compound $nbt, Entity $shootingEntity = null){
|
||||
$this->shootingEntity = $shootingEntity;
|
||||
parent::__construct($chunk, $nbt);
|
||||
}
|
||||
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Arrow");
|
||||
$this->setMaxHealth(1);
|
||||
$this->setHealth(1);
|
||||
if(isset($this->namedtag->Age)){
|
||||
$this->age = $this->namedtag["Age"];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function onUpdate($currentTick){
|
||||
if($this->closed){
|
||||
return false;
|
||||
@ -74,105 +51,11 @@ class Arrow extends Projectile{
|
||||
|
||||
$this->timings->startTiming();
|
||||
|
||||
$tickDiff = max(1, $currentTick - $this->lastUpdate);
|
||||
$this->lastUpdate = $currentTick;
|
||||
|
||||
$hasUpdate = $this->entityBaseTick($tickDiff);
|
||||
|
||||
if(!$this->dead){
|
||||
|
||||
$movingObjectPosition = null;
|
||||
|
||||
$this->motionY -= $this->gravity;
|
||||
|
||||
$this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z);
|
||||
|
||||
$moveVector = new Vector3($this->x + $this->motionX, $this->y + $this->motionY, $this->z + $this->motionZ);
|
||||
|
||||
$list = $this->getLevel()->getCollidingEntities($this->boundingBox->addCoord($this->motionX, $this->motionY, $this->motionZ)->expand(1, 1, 1), $this);
|
||||
|
||||
$nearDistance = PHP_INT_MAX;
|
||||
$nearEntity = null;
|
||||
|
||||
foreach($list as $entity){
|
||||
if(/*!$entity->canCollideWith($this) or */
|
||||
($entity === $this->shootingEntity and $this->ticksLived < 5)
|
||||
){
|
||||
continue;
|
||||
}
|
||||
|
||||
$axisalignedbb = $entity->boundingBox->grow(0.3, 0.3, 0.3);
|
||||
$ob = $axisalignedbb->calculateIntercept($this, $moveVector);
|
||||
|
||||
if($ob === null){
|
||||
continue;
|
||||
}
|
||||
|
||||
$distance = $this->distance($ob->hitVector);
|
||||
|
||||
if($distance < $nearDistance){
|
||||
$nearDistance = $distance;
|
||||
$nearEntity = $entity;
|
||||
}
|
||||
}
|
||||
|
||||
if($nearEntity !== null){
|
||||
$movingObjectPosition = MovingObjectPosition::fromEntity($nearEntity);
|
||||
}
|
||||
|
||||
if($movingObjectPosition !== null){
|
||||
if($movingObjectPosition->entityHit !== null){
|
||||
|
||||
$this->server->getPluginManager()->callEvent(new ProjectileHitEvent($this));
|
||||
|
||||
$motion = sqrt($this->motionX ** 2 + $this->motionY ** 2 + $this->motionZ ** 2);
|
||||
$damage = ceil($motion * $this->damage);
|
||||
|
||||
|
||||
$ev = new EntityDamageByEntityEvent($this->shootingEntity === null ? $this : $this->shootingEntity, $movingObjectPosition->entityHit, EntityDamageEvent::CAUSE_PROJECTILE, $damage);
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
|
||||
if(!$ev->isCancelled()){
|
||||
$movingObjectPosition->entityHit->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
|
||||
if($this->fireTicks > 0){
|
||||
$ev = new EntityCombustByEntityEvent($this, $movingObjectPosition->entityHit, 5);
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
if(!$ev->isCancelled()){
|
||||
$movingObjectPosition->entityHit->setOnFire($ev->getDuration());
|
||||
}
|
||||
}
|
||||
|
||||
$this->kill();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
|
||||
if($this->onGround and ($this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0)){
|
||||
$this->motionX = 0;
|
||||
$this->motionY = 0;
|
||||
$this->motionZ = 0;
|
||||
|
||||
$this->server->getPluginManager()->callEvent(new ProjectileHitEvent($this));
|
||||
}
|
||||
|
||||
if(!$this->onGround or $this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0){
|
||||
$f = sqrt(($this->motionX ** 2) + ($this->motionZ ** 2));
|
||||
$this->yaw = (atan2($this->motionX, $this->motionZ) * 180 / M_PI);
|
||||
$this->pitch = (atan2($this->motionY, $f) * 180 / M_PI);
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
if($this->age > 1200){
|
||||
$this->kill();
|
||||
$hasUpdate = true;
|
||||
}
|
||||
$this->updateMovement();
|
||||
$hasUpdate = parent::onUpdate($currentTick);
|
||||
|
||||
if($this->age > 1200){
|
||||
$this->kill();
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
$this->timings->stopTiming();
|
||||
@ -180,34 +63,6 @@ class Arrow extends Projectile{
|
||||
return $hasUpdate;
|
||||
}
|
||||
|
||||
public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){
|
||||
|
||||
}
|
||||
|
||||
public function heal($amount, $source = EntityRegainHealthEvent::CAUSE_MAGIC){
|
||||
|
||||
}
|
||||
|
||||
public function saveNBT(){
|
||||
parent::saveNBT();
|
||||
$this->namedtag->Age = new Short("Age", $this->age);
|
||||
}
|
||||
|
||||
public function getData(){
|
||||
$flags = 0;
|
||||
$flags |= $this->fireTicks > 0 ? 1 : 0;
|
||||
|
||||
return [
|
||||
0 => ["type" => 0, "value" => $flags],
|
||||
1 => ["type" => 1, "value" => $this->airTicks],
|
||||
16 => ["type" => 0, "value" => 0] //Is critical
|
||||
];
|
||||
}
|
||||
|
||||
public function canCollideWith(Entity $entity){
|
||||
return $entity instanceof Living and !$this->onGround;
|
||||
}
|
||||
|
||||
public function spawnTo(Player $player){
|
||||
$pk = new AddEntityPacket();
|
||||
$pk->type = Arrow::NETWORK_ID;
|
||||
|
@ -22,11 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Chicken extends Animal{
|
||||
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Chicken");
|
||||
}
|
||||
}
|
@ -22,10 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Cow extends Animal{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Cow");
|
||||
}
|
||||
|
||||
}
|
@ -22,10 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Creeper extends Monster implements Explosive{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Creeper");
|
||||
}
|
||||
|
||||
}
|
@ -22,10 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Egg extends Projectile{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Egg");
|
||||
}
|
||||
|
||||
}
|
@ -23,10 +23,7 @@ namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\inventory\InventoryHolder;
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Enderman extends Monster implements InventoryHolder{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Enderman");
|
||||
}
|
||||
|
||||
}
|
@ -40,7 +40,7 @@ use pocketmine\level\Location;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Math;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\metadata\Metadatable;
|
||||
use pocketmine\metadata\MetadataValue;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
@ -49,6 +49,7 @@ use pocketmine\nbt\tag\Double;
|
||||
use pocketmine\nbt\tag\Enum;
|
||||
use pocketmine\nbt\tag\Float;
|
||||
use pocketmine\nbt\tag\Short;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\Network;
|
||||
use pocketmine\network\protocol\MoveEntityPacket;
|
||||
use pocketmine\network\protocol\MovePlayerPacket;
|
||||
@ -59,12 +60,17 @@ use pocketmine\network\protocol\SetTimePacket;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\ChunkException;
|
||||
|
||||
abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
|
||||
const NETWORK_ID = -1;
|
||||
|
||||
public static $entityCount = 1;
|
||||
/** @var Entity[] */
|
||||
private static $knownEntities = [];
|
||||
private static $shortNames = [];
|
||||
|
||||
/**
|
||||
* @var Player[]
|
||||
@ -122,7 +128,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
protected $ySize = 0;
|
||||
protected $stepHeight = 0;
|
||||
public $keepMovement = true;
|
||||
public $keepMovement = false;
|
||||
|
||||
public $fallDistance;
|
||||
public $ticksLived;
|
||||
@ -134,7 +140,10 @@ abstract class Entity extends Location implements Metadatable{
|
||||
public $canCollide = true;
|
||||
|
||||
protected $isStatic = false;
|
||||
protected $isColliding = false;
|
||||
|
||||
public $isCollided = false;
|
||||
public $isCollidedHorizontally = false;
|
||||
public $isCollidedVertically = false;
|
||||
|
||||
public $noDamageTicks;
|
||||
private $justCreated;
|
||||
@ -155,7 +164,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
public function __construct(FullChunk $chunk, Compound $nbt){
|
||||
if($chunk === null or $chunk->getProvider() === null){
|
||||
throw new \Exception("Invalid garbage Chunk given to Entity");
|
||||
throw new ChunkException("Invalid garbage Chunk given to Entity");
|
||||
}
|
||||
|
||||
$this->timings = Timings::getEntityTimings($this);
|
||||
@ -167,6 +176,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
$this->id = Entity::$entityCount++;
|
||||
$this->justCreated = true;
|
||||
$this->namedtag = $nbt;
|
||||
|
||||
$this->chunk = $chunk;
|
||||
$this->setLevel($chunk->getProvider()->getLevel());
|
||||
$this->server = $chunk->getProvider()->getLevel()->getServer();
|
||||
@ -219,7 +229,54 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $type
|
||||
* @param FullChunk $chunk
|
||||
* @param Compound $nbt
|
||||
* @param $args
|
||||
*
|
||||
* @return Entity
|
||||
*/
|
||||
public static function createEntity($type, FullChunk $chunk, Compound $nbt, ...$args){
|
||||
if(isset(self::$knownEntities[$type])){
|
||||
$class = self::$knownEntities[$type];
|
||||
return new $class($chunk, $nbt, ...$args);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function registerEntity($className, $force = false){
|
||||
$class = new \ReflectionClass($className);
|
||||
if(is_a($className, Entity::class, true) and !$class->isAbstract()){
|
||||
if($className::NETWORK_ID !== -1){
|
||||
self::$knownEntities[$className::NETWORK_ID] = $className;
|
||||
}elseif(!$force){
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$knownEntities[$class->getShortName()] = $className;
|
||||
self::$shortNames[$className] = $class->getShortName();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the short save name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSaveId(){
|
||||
return self::$shortNames[static::class];
|
||||
}
|
||||
|
||||
public function saveNBT(){
|
||||
if(!($this instanceof Player)){
|
||||
$this->namedtag->id = new String("id", $this->getSaveId());
|
||||
}
|
||||
|
||||
$this->namedtag->Pos = new Enum("Pos", [
|
||||
new Double(0, $this->x),
|
||||
new Double(1, $this->y),
|
||||
@ -293,7 +350,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
*/
|
||||
public function despawnFrom(Player $player){
|
||||
if(isset($this->hasSpawned[$player->getID()])){
|
||||
$pk = new RemoveEntityPacket;
|
||||
$pk = new RemoveEntityPacket();
|
||||
$pk->eid = $this->id;
|
||||
$player->dataPacket($pk);
|
||||
unset($this->hasSpawned[$player->getID()]);
|
||||
@ -347,7 +404,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
* @param int|EntityDamageEvent $type
|
||||
*/
|
||||
public function setLastDamageCause($type){
|
||||
$this->lastDamageCause = $type;
|
||||
$this->lastDamageCause = $type instanceof EntityDamageEvent ? clone $type : $type;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -387,15 +444,17 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
$list = $this->level->getCollisionBlocks($this->boundingBox);
|
||||
|
||||
if(count($list) === 0 and !$this->level->isFullBlock(new Vector3($i, $j, $k))){
|
||||
$v = new Vector3($i, $j, $k);
|
||||
|
||||
if(count($list) === 0 and !$this->level->isFullBlock($v->setComponents($i, $j, $k))){
|
||||
return false;
|
||||
}else{
|
||||
$flag = !$this->level->isFullBlock(new Vector3($i - 1, $j, $k));
|
||||
$flag1 = !$this->level->isFullBlock(new Vector3($i + 1, $j, $k));
|
||||
//$flag2 = !$this->level->isFullBlock(new Vector3($i, $j - 1, $k));
|
||||
$flag3 = !$this->level->isFullBlock(new Vector3($i, $j + 1, $k));
|
||||
$flag4 = !$this->level->isFullBlock(new Vector3($i, $j, $k - 1));
|
||||
$flag5 = !$this->level->isFullBlock(new Vector3($i, $j, $k + 1));
|
||||
$flag = !$this->level->isFullBlock($v->setComponents($i - 1, $j, $k));
|
||||
$flag1 = !$this->level->isFullBlock($v->setComponents($i + 1, $j, $k));
|
||||
//$flag2 = !$this->level->isFullBlock($v->setComponents($i, $j - 1, $k));
|
||||
$flag3 = !$this->level->isFullBlock($v->setComponents($i, $j + 1, $k));
|
||||
$flag4 = !$this->level->isFullBlock($v->setComponents($i, $j, $k - 1));
|
||||
$flag5 = !$this->level->isFullBlock($v->setComponents($i, $j, $k + 1));
|
||||
|
||||
$direction = 3; //UP!
|
||||
$limit = 9999;
|
||||
@ -483,10 +542,8 @@ abstract class Entity extends Location implements Metadatable{
|
||||
$this->checkBlockCollision();
|
||||
|
||||
if($this->y < 0 and $this->dead !== true){
|
||||
$this->server->getPluginManager()->callEvent($ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_VOID, 10));
|
||||
if(!$ev->isCancelled()){
|
||||
$this->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_VOID, 10);
|
||||
$this->attack($ev->getFinalDamage(), $ev);
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
@ -499,10 +556,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}else{
|
||||
if(($this->fireTicks % 20) === 0 or $tickDiff > 20){
|
||||
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_FIRE_TICK, 1);
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
if(!$ev->isCancelled()){
|
||||
$this->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
$this->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
$this->fireTicks -= $tickDiff;
|
||||
}
|
||||
@ -532,7 +586,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
$this->lastPitch = $this->pitch;
|
||||
|
||||
if($this instanceof Human){
|
||||
$pk = new MovePlayerPacket;
|
||||
$pk = new MovePlayerPacket();
|
||||
$pk->eid = $this->id;
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
@ -556,7 +610,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
$this->lastMotionY = $this->motionY;
|
||||
$this->lastMotionZ = $this->motionZ;
|
||||
|
||||
$pk = new SetEntityMotionPacket;
|
||||
$pk = new SetEntityMotionPacket();
|
||||
$pk->entities = [
|
||||
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
|
||||
];
|
||||
@ -675,10 +729,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
public function fall($fallDistance){
|
||||
$damage = floor($fallDistance - 3);
|
||||
if($damage > 0){
|
||||
$this->server->getPluginManager()->callEvent($ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_FALL, $damage));
|
||||
if($ev->isCancelled()){
|
||||
return;
|
||||
}
|
||||
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_FALL, $damage);
|
||||
$this->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
}
|
||||
@ -707,22 +758,20 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}
|
||||
|
||||
$this->level->removeEntity($this);
|
||||
$this->chunk->removeEntity($this);
|
||||
if($this->chunk !== null){
|
||||
$this->chunk->removeEntity($this);
|
||||
}
|
||||
$this->despawnFromAll();
|
||||
if($this instanceof Player){
|
||||
foreach($this->usedChunks as $index => $d){
|
||||
$X = null;
|
||||
$Z = null;
|
||||
Level::getXZ($index, $X, $Z);
|
||||
foreach($this->level->getChunkEntities($X, $Z) as $entity){
|
||||
$entity->despawnFrom($this);
|
||||
}
|
||||
|
||||
$this->unloadChunk($X, $Z);
|
||||
}
|
||||
$this->level->freeAllChunks($this);
|
||||
}
|
||||
}
|
||||
$this->setLevel($targetLevel, $this instanceof Player ? true : false); //Hard reference
|
||||
$this->setLevel($targetLevel);
|
||||
$this->level->addEntity($this);
|
||||
if($this instanceof Player){
|
||||
$this->usedChunks = [];
|
||||
@ -745,10 +794,10 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}
|
||||
|
||||
public function isInsideOfWater(){
|
||||
$block = $this->level->getBlock($pos = (new Vector3($this->x, $y = ($this->y + $this->getEyeHeight()), $this->z))->floor());
|
||||
$block = $this->level->getBlock(new Vector3(Math::floorFloat($this->x), Math::floorFloat($y = ($this->y + $this->getEyeHeight())), Math::floorFloat($this->z)));
|
||||
|
||||
if($block instanceof Water){
|
||||
$f = ($pos->y + 1) - ($block->getFluidHeightPercent() - 0.1111111);
|
||||
$f = ($block->y + 1) - ($block->getFluidHeightPercent() - 0.1111111);
|
||||
return $y < $f;
|
||||
}
|
||||
|
||||
@ -756,7 +805,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}
|
||||
|
||||
public function isInsideOfSolid(){
|
||||
$block = $this->level->getBlock($pos = (new Vector3($this->x, $y = ($this->y + $this->getEyeHeight()), $this->z))->floor());
|
||||
$block = $this->level->getBlock(new Vector3(Math::floorFloat($this->x), Math::floorFloat($y = ($this->y + $this->getEyeHeight())), Math::floorFloat($this->z)));
|
||||
|
||||
$bb = $block->getBoundingBox();
|
||||
|
||||
@ -766,23 +815,17 @@ abstract class Entity extends Location implements Metadatable{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function collision(){
|
||||
$this->isColliding = true;
|
||||
$this->fallDistance = 0;
|
||||
}
|
||||
|
||||
public function move($dx, $dy, $dz){
|
||||
|
||||
if($dx == 0 and $dz == 0 and $dy == 0){
|
||||
return true;
|
||||
}
|
||||
|
||||
//if($this->inBlock){ //TODO: noclip
|
||||
// $this->boundingBox->offset($dx, $dy, $dz);
|
||||
// $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;
|
||||
//}else{
|
||||
if($this->keepMovement){
|
||||
$this->boundingBox->offset($dx, $dy, $dz);
|
||||
$this->setPosition(new Vector3(($this->boundingBox->minX + $this->boundingBox->maxX) / 2, $this->boundingBox->minY - $this->ySize, ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2));
|
||||
$this->onGround = $this instanceof Player ? true : false;
|
||||
}else{
|
||||
|
||||
Timings::$entityMoveTimer->startTiming();
|
||||
|
||||
@ -832,7 +875,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
//TODO: big messy loop
|
||||
}*/
|
||||
|
||||
$list = $this->level->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox($dx, $dy, $dz), false);
|
||||
$list = $this->level->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox($dx, $dy, $dz));
|
||||
|
||||
|
||||
foreach($list as $bb){
|
||||
@ -841,7 +884,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
$this->boundingBox->offset(0, $dy, 0);
|
||||
|
||||
if(!$this->keepMovement and $movY != $dy){
|
||||
if($movY != $dy){
|
||||
$dx = 0;
|
||||
$dy = 0;
|
||||
$dz = 0;
|
||||
@ -855,7 +898,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
$this->boundingBox->offset($dx, 0, 0);
|
||||
|
||||
if(!$this->keepMovement and $movX != $dx){
|
||||
if($movX != $dx){
|
||||
$dx = 0;
|
||||
$dy = 0;
|
||||
$dz = 0;
|
||||
@ -867,7 +910,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
$this->boundingBox->offset(0, 0, $dz);
|
||||
|
||||
if(!$this->keepMovement and $movZ != $dz){
|
||||
if($movZ != $dz){
|
||||
$dx = 0;
|
||||
$dy = 0;
|
||||
$dz = 0;
|
||||
@ -893,7 +936,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}
|
||||
|
||||
$this->boundingBox->offset(0, $dy, 0);
|
||||
if(!$this->keepMovement and $movY != $dy){
|
||||
if($movY != $dy){
|
||||
$dx = 0;
|
||||
$dy = 0;
|
||||
$dz = 0;
|
||||
@ -904,7 +947,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}
|
||||
|
||||
$this->boundingBox->offset($dx, 0, 0);
|
||||
if(!$this->keepMovement and $movX != $dx){
|
||||
if($movX != $dx){
|
||||
$dx = 0;
|
||||
$dy = 0;
|
||||
$dz = 0;
|
||||
@ -915,13 +958,13 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}
|
||||
|
||||
$this->boundingBox->offset(0, 0, $dz);
|
||||
if(!$this->keepMovement and $movZ != $dz){
|
||||
if($movZ != $dz){
|
||||
$dx = 0;
|
||||
$dy = 0;
|
||||
$dz = 0;
|
||||
}
|
||||
|
||||
if(!$this->keepMovement and $movY != $dy){
|
||||
if($movY != $dy){
|
||||
$dx = 0;
|
||||
$dy = 0;
|
||||
$dz = 0;
|
||||
@ -956,18 +999,20 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}else{
|
||||
|
||||
if($this instanceof Player){
|
||||
if(($this->onGround and $movY != 0) or (!$this->onGround and $movY < 0)){
|
||||
if(!$this->onGround or $movY != 0){
|
||||
$bb = clone $this->boundingBox;
|
||||
$bb->maxY = $bb->minY + 0.5;
|
||||
$bb->maxY = $bb->minY + 1;
|
||||
if(count($this->level->getCollisionBlocks($bb->expand(0.01, 0.01, 0.01))) > 0){
|
||||
$isColliding = true;
|
||||
$this->onGround = true;
|
||||
}else{
|
||||
$isColliding = false;
|
||||
$this->onGround = false;
|
||||
}
|
||||
|
||||
$this->onGround = ($movY <= 0 and $isColliding);
|
||||
}
|
||||
$this->isCollided = $this->onGround;
|
||||
}else{
|
||||
$this->isCollidedVertically = $movY != $dy;
|
||||
$this->isCollidedHorizontally = ($movX != $dx or $movZ != $dz);
|
||||
$this->isCollided = ($this->isCollidedHorizontally or $this->isCollidedVertically);
|
||||
$this->onGround = ($movY != $dy and $movY < 0);
|
||||
}
|
||||
$this->updateFallState($dy, $this->onGround);
|
||||
@ -990,7 +1035,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
Timings::$entityMoveTimer->stopTiming();
|
||||
|
||||
return $result;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
protected function checkBlockCollision(){
|
||||
@ -1002,11 +1047,12 @@ abstract class Entity extends Location implements Metadatable{
|
||||
$maxZ = Math::floorFloat($this->boundingBox->maxZ - 0.001);
|
||||
|
||||
$vector = new Vector3(0, 0, 0);
|
||||
$v = new Vector3(0, 0, 0);
|
||||
|
||||
for($z = $minZ; $z <= $maxZ; ++$z){
|
||||
for($x = $minX; $x <= $maxX; ++$x){
|
||||
for($y = $minY; $y <= $maxY; ++$y){
|
||||
$block = $this->level->getBlock(new Vector3($x, $y, $z));
|
||||
for($v->z = $minZ; $v->z <= $maxZ; ++$v->z){
|
||||
for($v->x = $minX; $v->x <= $maxX; ++$v->x){
|
||||
for($v->y = $minY; $v->y <= $maxY; ++$v->y){
|
||||
$block = $this->level->getBlock($v);
|
||||
if($block !== null and $block->hasEntityCollision){
|
||||
$block->onEntityCollide($this);
|
||||
if(!($this instanceof Player)){
|
||||
@ -1043,6 +1089,10 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}
|
||||
|
||||
public function setPosition(Vector3 $pos){
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($pos instanceof Position and $pos->level instanceof Level and $pos->level !== $this->level){
|
||||
if($this->switchLevel($pos->getLevel()) === false){
|
||||
return false;
|
||||
@ -1102,7 +1152,7 @@ abstract class Entity extends Location implements Metadatable{
|
||||
|
||||
if(!$this->justCreated){
|
||||
if($this instanceof Player){
|
||||
$pk = new SetEntityMotionPacket;
|
||||
$pk = new SetEntityMotionPacket();
|
||||
$pk->entities = [
|
||||
[0, $this->motionX, $this->motionY, $this->motionZ]
|
||||
];
|
||||
@ -1178,17 +1228,18 @@ abstract class Entity extends Location implements Metadatable{
|
||||
}
|
||||
|
||||
public function close(){
|
||||
if($this->closed === false){
|
||||
if(!$this->closed){
|
||||
$this->server->getPluginManager()->callEvent(new EntityDespawnEvent($this));
|
||||
$this->closed = true;
|
||||
unset($this->level->updateEntities[$this->id]);
|
||||
if($this->chunk instanceof FullChunk){
|
||||
$this->chunk->removeEntity($this);
|
||||
}
|
||||
if(($level = $this->level) instanceof Level){
|
||||
$level->removeEntity($this);
|
||||
if($this->level instanceof Level){
|
||||
$this->level->removeEntity($this);
|
||||
}
|
||||
$this->despawnFromAll();
|
||||
$this->level = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,15 +26,15 @@ use pocketmine\block\Block;
|
||||
use pocketmine\event\entity\EntityBlockChangeEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\event\entity\EntityRegainHealthEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Item as ItemItem;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\nbt\tag\Int;
|
||||
use pocketmine\network\protocol\AddEntityPacket;
|
||||
use pocketmine\network\protocol\SetEntityMotionPacket;
|
||||
use pocketmine\Player;
|
||||
|
||||
class FallingBlock extends Entity{
|
||||
|
||||
class FallingSand extends Entity{
|
||||
const NETWORK_ID = 66;
|
||||
|
||||
public $width = 0.98;
|
||||
@ -44,13 +44,20 @@ class FallingBlock extends Entity{
|
||||
protected $gravity = 0.04;
|
||||
protected $drag = 0.02;
|
||||
protected $blockId = 0;
|
||||
protected $damage;
|
||||
|
||||
public $canCollide = false;
|
||||
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "FallingSand");
|
||||
if(isset($this->namedtag->Tile)){
|
||||
if(isset($this->namedtag->TileID)){
|
||||
$this->blockId = $this->namedtag["TileID"];
|
||||
}elseif(isset($this->namedtag->Tile)){
|
||||
$this->blockId = $this->namedtag["Tile"];
|
||||
$this->namedtag["TileID"] = new Int("TileID", $this->blockId);
|
||||
}
|
||||
|
||||
if(isset($this->namedtag->Data)){
|
||||
$this->damage = $this->namedtag["Data"];
|
||||
}
|
||||
|
||||
if($this->blockId === 0){
|
||||
@ -81,12 +88,12 @@ class FallingBlock extends Entity{
|
||||
|
||||
if(!$this->dead){
|
||||
if($this->ticksLived === 1){
|
||||
$block = $this->level->getBlock($this->floor());
|
||||
$block = $this->level->getBlock($pos = (new Vector3($this->x, $this->y, $this->z))->floor());
|
||||
if($block->getID() != $this->blockId){
|
||||
$this->kill();
|
||||
return true;
|
||||
}
|
||||
$this->level->setBlock($this->floor(), Block::get(0), true);
|
||||
$this->level->setBlock($pos, Block::get(0), true);
|
||||
|
||||
}
|
||||
|
||||
@ -100,15 +107,15 @@ class FallingBlock extends Entity{
|
||||
$this->motionY *= 1 - $this->drag;
|
||||
$this->motionZ *= $friction;
|
||||
|
||||
$pos = $this->floor();
|
||||
$pos = (new Vector3($this->x, $this->y, $this->z))->floor();
|
||||
|
||||
if($this->onGround){
|
||||
$this->kill();
|
||||
$block = $this->level->getBlock($pos);
|
||||
if(!$block->isFullBlock){
|
||||
$this->getLevel()->dropItem($this, Item::get($this->getBlock(), 0, 1));
|
||||
$this->getLevel()->dropItem($this, ItemItem::get($this->getBlock(), $this->getDamage(), 1));
|
||||
}else{
|
||||
$this->server->getPluginManager()->callEvent($ev = new EntityBlockChangeEvent($this, $block, Block::get($this->getBlock(), 0)));
|
||||
$this->server->getPluginManager()->callEvent($ev = new EntityBlockChangeEvent($this, $block, Block::get($this->getBlock(), $this->getDamage())));
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getLevel()->setBlock($pos, $ev->getTo(), true);
|
||||
}
|
||||
@ -119,15 +126,19 @@ class FallingBlock extends Entity{
|
||||
$this->updateMovement();
|
||||
}
|
||||
|
||||
return $hasUpdate or !$this->onGround or ($this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0);
|
||||
return $hasUpdate or !$this->onGround or $this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0;
|
||||
}
|
||||
|
||||
public function getBlock(){
|
||||
return $this->blockId;
|
||||
}
|
||||
public function getDamage(){
|
||||
return $this->damage;
|
||||
}
|
||||
|
||||
public function saveNBT(){
|
||||
$this->namedtag->Tile = new Byte("Tile", $this->blockId);
|
||||
$this->namedtag->TileID = new Int("TileID", $this->blockId);
|
||||
$this->namedtag->Data = new Byte("Data", $this->damage);
|
||||
}
|
||||
|
||||
public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){
|
||||
@ -139,16 +150,16 @@ class FallingBlock extends Entity{
|
||||
}
|
||||
|
||||
public function spawnTo(Player $player){
|
||||
$pk = new AddEntityPacket;
|
||||
$pk->type = FallingBlock::NETWORK_ID;
|
||||
$pk = new AddEntityPacket();
|
||||
$pk->type = FallingSand::NETWORK_ID;
|
||||
$pk->eid = $this->getID();
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
$pk->z = $this->z;
|
||||
$pk->did = -$this->getBlock();
|
||||
$pk->did = -($this->getBlock() | $this->getDamage() << 0x10);
|
||||
$player->dataPacket($pk);
|
||||
|
||||
$pk = new SetEntityMotionPacket;
|
||||
$pk = new SetEntityMotionPacket();
|
||||
$pk->entities = [
|
||||
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
|
||||
];
|
||||
@ -156,4 +167,4 @@ class FallingBlock extends Entity{
|
||||
|
||||
parent::spawnTo($player);
|
||||
}
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ namespace pocketmine\entity;
|
||||
|
||||
use pocketmine\inventory\InventoryHolder;
|
||||
use pocketmine\inventory\PlayerInventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Item as ItemItem;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
@ -67,9 +67,9 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
if($item["Slot"] >= 0 and $item["Slot"] < 9){ //Hotbar
|
||||
$this->inventory->setHotbarSlotIndex($item["Slot"], isset($item["TrueSlot"]) ? $item["TrueSlot"] : -1);
|
||||
}elseif($item["Slot"] >= 100 and $item["Slot"] < 104){ //Armor
|
||||
$this->inventory->setItem($this->inventory->getSize() + $item["Slot"] - 100, Item::get($item["id"], $item["Damage"], $item["Count"]), $this);
|
||||
$this->inventory->setItem($this->inventory->getSize() + $item["Slot"] - 100, ItemItem::get($item["id"], $item["Damage"], $item["Count"]), $this);
|
||||
}else{
|
||||
$this->inventory->setItem($item["Slot"] - 9, Item::get($item["id"], $item["Damage"], $item["Count"]), $this);
|
||||
$this->inventory->setItem($item["Slot"] - 9, ItemItem::get($item["id"], $item["Damage"], $item["Count"]), $this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,7 +140,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
//Armor
|
||||
for($slot = 100; $slot < 104; ++$slot){
|
||||
$item = $this->inventory->getItem($this->inventory->getSize() + $slot - 100);
|
||||
if($item instanceof Item and $item->getID() !== Item::AIR){
|
||||
if($item instanceof ItemItem and $item->getID() !== ItemItem::AIR){
|
||||
$this->namedtag->Inventory[$slot] = new Compound(false, [
|
||||
new Byte("Count", $item->getCount()),
|
||||
new Short("Damage", $item->getDamage()),
|
||||
@ -156,7 +156,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
if($player !== $this and !isset($this->hasSpawned[$player->getID()])){
|
||||
$this->hasSpawned[$player->getID()] = $player;
|
||||
|
||||
$pk = new AddPlayerPacket;
|
||||
$pk = new AddPlayerPacket();
|
||||
$pk->clientID = 0;
|
||||
if($player->getRemoveFormat()){
|
||||
$pk->username = TextFormat::clean($this->nameTag);
|
||||
@ -174,7 +174,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
$pk->metadata = $this->getData();
|
||||
$player->dataPacket($pk);
|
||||
|
||||
$pk = new SetEntityMotionPacket;
|
||||
$pk = new SetEntityMotionPacket();
|
||||
$pk->entities = [
|
||||
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
|
||||
];
|
||||
@ -188,7 +188,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
|
||||
public function despawnFrom(Player $player){
|
||||
if(isset($this->hasSpawned[$player->getID()])){
|
||||
$pk = new RemovePlayerPacket;
|
||||
$pk = new RemovePlayerPacket();
|
||||
$pk->eid = $this->id;
|
||||
$pk->clientID = 0;
|
||||
$player->dataPacket($pk);
|
||||
@ -208,22 +208,19 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
|
||||
17 => ["type" => 6, "value" => [0, 0, 0]],
|
||||
];
|
||||
|
||||
/*if($this->class === ENTITY_MOB and $this->type === MOB_SHEEP){
|
||||
if(!isset($this->data["Sheared"])){
|
||||
$this->data["Sheared"] = 0;
|
||||
$this->data["Color"] = mt_rand(0,15);
|
||||
}
|
||||
$d[16]["value"] = (($this->data["Sheared"] == 1 ? 1:0) << 4) | ($this->data["Color"] & 0x0F);
|
||||
}elseif($this->type === OBJECT_PRIMEDTNT){
|
||||
$d[16]["value"] = (int) max(0, $this->data["fuse"] - (microtime(true) - $this->spawntime) * 20);
|
||||
}elseif($this->class === ENTITY_PLAYER){
|
||||
if($this->player->sleeping !== false){
|
||||
$d[16]["value"] = 2;
|
||||
$d[17]["value"] = array($this->player->sleeping->x, $this->player->sleeping->y, $this->player->sleeping->z);
|
||||
}
|
||||
}*/
|
||||
|
||||
return $d;
|
||||
}
|
||||
|
||||
public function close(){
|
||||
if(!$this->closed){
|
||||
if(!($this instanceof Player) or $this->loggedIn){
|
||||
foreach($this->getInventory()->getViewers() as $player){
|
||||
$this->getInventory()->close($player);
|
||||
}
|
||||
}
|
||||
$this->inventory = null;
|
||||
parent::close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\event\entity\EntityRegainHealthEvent;
|
||||
use pocketmine\event\entity\ItemDespawnEvent;
|
||||
use pocketmine\event\entity\ItemSpawnEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Item as ItemItem;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
@ -35,12 +35,13 @@ use pocketmine\network\protocol\AddItemEntityPacket;
|
||||
use pocketmine\network\protocol\SetEntityMotionPacket;
|
||||
use pocketmine\Player;
|
||||
|
||||
class DroppedItem extends Entity{
|
||||
class Item extends Entity{
|
||||
const NETWORK_ID = 64;
|
||||
|
||||
protected $owner = null;
|
||||
protected $thrower = null;
|
||||
protected $pickupDelay = 0;
|
||||
/** @var Item */
|
||||
/** @var ItemItem */
|
||||
protected $item;
|
||||
|
||||
public $width = 0.25;
|
||||
@ -52,7 +53,6 @@ class DroppedItem extends Entity{
|
||||
public $canCollide = false;
|
||||
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Item");
|
||||
$this->setMaxHealth(5);
|
||||
$this->setHealth($this->namedtag["Health"]);
|
||||
if(isset($this->namedtag->Age)){
|
||||
@ -67,7 +67,7 @@ class DroppedItem extends Entity{
|
||||
if(isset($this->namedtag->Thrower)){
|
||||
$this->thrower = $this->namedtag["Thrower"];
|
||||
}
|
||||
$this->item = Item::get($this->namedtag->Item["id"], $this->namedtag->Item["Damage"], $this->namedtag->Item["Count"]);
|
||||
$this->item = ItemItem::get($this->namedtag->Item["id"], $this->namedtag->Item["Damage"], $this->namedtag->Item["Count"]);
|
||||
|
||||
|
||||
$this->server->getPluginManager()->callEvent(new ItemSpawnEvent($this));
|
||||
@ -93,7 +93,7 @@ class DroppedItem extends Entity{
|
||||
|
||||
$this->motionY -= $this->gravity;
|
||||
|
||||
$this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z);
|
||||
$this->keepMovement = $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;
|
||||
@ -126,10 +126,17 @@ class DroppedItem extends Entity{
|
||||
|
||||
$this->timings->stopTiming();
|
||||
|
||||
return $hasUpdate or !$this->onGround or ($this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0);
|
||||
return $hasUpdate or !$this->onGround or $this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0;
|
||||
}
|
||||
|
||||
public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){
|
||||
if($source instanceof EntityDamageEvent){
|
||||
$this->server->getPluginManager()->callEvent($source);
|
||||
$damage = $source->getFinalDamage();
|
||||
if($source->isCancelled()){
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->setLastDamageCause($source);
|
||||
$this->setHealth($this->getHealth() - $damage);
|
||||
}
|
||||
@ -166,7 +173,7 @@ class DroppedItem extends Entity{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Item
|
||||
* @return ItemItem
|
||||
*/
|
||||
public function getItem(){
|
||||
return $this->item;
|
||||
@ -230,7 +237,7 @@ class DroppedItem extends Entity{
|
||||
$pk->item = $this->getItem();
|
||||
$player->dataPacket($pk);
|
||||
|
||||
$pk = new SetEntityMotionPacket;
|
||||
$pk = new SetEntityMotionPacket();
|
||||
$pk->entities = [
|
||||
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
|
||||
];
|
@ -28,7 +28,7 @@ use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\event\entity\EntityDeathEvent;
|
||||
use pocketmine\event\entity\EntityRegainHealthEvent;
|
||||
use pocketmine\event\Timings;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Item as ItemItem;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\Short;
|
||||
use pocketmine\network\protocol\EntityEventPacket;
|
||||
@ -65,13 +65,28 @@ abstract class Living extends Entity implements Damageable{
|
||||
public function hasLineOfSight(Entity $entity){
|
||||
//TODO: head height
|
||||
return true;
|
||||
//return $this->getLevel()->rayTraceBlocks(new Vector3($this->x, $this->y + $this->height, $this->z), new Vector3($entity->x, $entity->y + $entity->height, $entity->z)) === null;
|
||||
//return $this->getLevel()->rayTraceBlocks(Vector3::createVector($this->x, $this->y + $this->height, $this->z), Vector3::createVector($entity->x, $entity->y + $entity->height, $entity->z)) === null;
|
||||
}
|
||||
|
||||
public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){
|
||||
if($this->attackTime > 0){
|
||||
$lastCause = $this->getLastDamageCause();
|
||||
if($lastCause instanceof EntityDamageEvent and $lastCause->getDamage() >= $damage){
|
||||
if($source instanceof EntityDamageEvent){
|
||||
$source->setCancelled();
|
||||
$this->server->getPluginManager()->callEvent($source);
|
||||
$damage = $source->getFinalDamage();
|
||||
if($source->isCancelled()){
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}elseif($source instanceof EntityDamageEvent){
|
||||
$this->server->getPluginManager()->callEvent($source);
|
||||
$damage = $source->getFinalDamage();
|
||||
if($source->isCancelled()){
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -132,13 +147,11 @@ abstract class Living extends Entity implements Damageable{
|
||||
|
||||
public function entityBaseTick($tickDiff = 1){
|
||||
Timings::$timerEntityBaseTick->startTiming();
|
||||
parent::entityBaseTick();
|
||||
parent::entityBaseTick($tickDiff);
|
||||
|
||||
if($this->dead !== true and $this->isInsideOfSolid()){
|
||||
$this->server->getPluginManager()->callEvent($ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_SUFFOCATION, 1));
|
||||
if(!$ev->isCancelled()){
|
||||
$this->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_SUFFOCATION, 1);
|
||||
$this->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
|
||||
if($this->dead !== true and $this->isInsideOfWater()){
|
||||
@ -146,10 +159,8 @@ abstract class Living extends Entity implements Damageable{
|
||||
if($this->airTicks <= -20){
|
||||
$this->airTicks = 0;
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_DROWNING, 2));
|
||||
if(!$ev->isCancelled()){
|
||||
$this->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
$ev = new EntityDamageEvent($this, EntityDamageEvent::CAUSE_DROWNING, 2);
|
||||
$this->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
}else{
|
||||
$this->airTicks = 300;
|
||||
@ -163,7 +174,7 @@ abstract class Living extends Entity implements Damageable{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Item[]
|
||||
* @return ItemItem[]
|
||||
*/
|
||||
public function getDrops(){
|
||||
return [];
|
||||
@ -186,15 +197,18 @@ abstract class Living extends Entity implements Damageable{
|
||||
}
|
||||
|
||||
$blocks = [];
|
||||
$nextIndex = 0;
|
||||
|
||||
$itr = new BlockIterator($this->level, $this->getPosition(), $this->getDirectionVector(), $this->getEyeHeight(), $maxDistance);
|
||||
|
||||
while($itr->valid()){
|
||||
$itr->next();
|
||||
$block = $itr->current();
|
||||
$blocks[] = $block;
|
||||
$blocks[$nextIndex++] = $block;
|
||||
|
||||
if($maxLength !== 0 and count($blocks) > $maxLength){
|
||||
array_shift($blocks);
|
||||
--$nextIndex;
|
||||
}
|
||||
|
||||
$id = $block->getID();
|
||||
|
@ -22,10 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
class Ozelot extends Animal implements Tameable{
|
||||
|
||||
class Ocelot extends Animal implements Tameable{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Ozelot");
|
||||
}
|
||||
}
|
@ -22,10 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Painting extends Hanging{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Painting");
|
||||
}
|
||||
|
||||
}
|
@ -22,10 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Pig extends Animal implements Rideable{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Pig");
|
||||
}
|
||||
|
||||
}
|
@ -22,10 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class PigZombie extends Zombie{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "PigZombie");
|
||||
}
|
||||
|
||||
}
|
@ -27,7 +27,6 @@ use pocketmine\event\entity\EntityRegainHealthEvent;
|
||||
use pocketmine\event\entity\ExplosionPrimeEvent;
|
||||
use pocketmine\level\Explosion;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\network\protocol\AddEntityPacket;
|
||||
use pocketmine\network\protocol\SetEntityMotionPacket;
|
||||
use pocketmine\Player;
|
||||
@ -47,7 +46,6 @@ class PrimedTNT extends Entity implements Explosive{
|
||||
public $canCollide = false;
|
||||
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "PrimedTNT");
|
||||
if(isset($this->namedtag->Fuse)){
|
||||
$this->fuse = $this->namedtag["Fuse"];
|
||||
}else{
|
||||
@ -116,7 +114,7 @@ class PrimedTNT extends Entity implements Explosive{
|
||||
}
|
||||
|
||||
|
||||
return $hasUpdate or $this->fuse > 0 or ($this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0);
|
||||
return $hasUpdate or $this->fuse >= 0 or $this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0;
|
||||
}
|
||||
|
||||
public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){
|
||||
|
@ -22,6 +22,171 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\event\entity\EntityCombustByEntityEvent;
|
||||
use pocketmine\event\entity\EntityDamageByChildEntityEvent;
|
||||
use pocketmine\event\entity\EntityDamageByEntityEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\event\entity\EntityRegainHealthEvent;
|
||||
use pocketmine\event\entity\ProjectileHitEvent;
|
||||
use pocketmine\level\MovingObjectPosition;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\Short;
|
||||
|
||||
abstract class Projectile extends Entity{
|
||||
/** @var Entity */
|
||||
public $shootingEntity = null;
|
||||
protected $damage = 0;
|
||||
|
||||
private $hadCollision = false;
|
||||
|
||||
protected function initEntity(){
|
||||
$this->setMaxHealth(1);
|
||||
$this->setHealth(1);
|
||||
if(isset($this->namedtag->Age)){
|
||||
$this->age = $this->namedtag["Age"];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function canCollideWith(Entity $entity){
|
||||
return $entity instanceof Living and !$this->onGround;
|
||||
}
|
||||
|
||||
public function getData(){
|
||||
$flags = 0;
|
||||
$flags |= $this->fireTicks > 0 ? 1 : 0;
|
||||
|
||||
return [
|
||||
0 => ["type" => 0, "value" => $flags],
|
||||
1 => ["type" => 1, "value" => $this->airTicks],
|
||||
16 => ["type" => 0, "value" => 0] //Is critical
|
||||
];
|
||||
}
|
||||
|
||||
public function saveNBT(){
|
||||
parent::saveNBT();
|
||||
$this->namedtag->Age = new Short("Age", $this->age);
|
||||
}
|
||||
|
||||
public function attack($damage, $source = EntityDamageEvent::CAUSE_MAGIC){
|
||||
|
||||
}
|
||||
|
||||
public function heal($amount, $source = EntityRegainHealthEvent::CAUSE_MAGIC){
|
||||
|
||||
}
|
||||
|
||||
public function onUpdate($currentTick){
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$tickDiff = max(1, $currentTick - $this->lastUpdate);
|
||||
$this->lastUpdate = $currentTick;
|
||||
|
||||
$hasUpdate = $this->entityBaseTick($tickDiff);
|
||||
|
||||
if(!$this->dead){
|
||||
|
||||
$movingObjectPosition = null;
|
||||
|
||||
if(!$this->isCollided){
|
||||
$this->motionY -= $this->gravity;
|
||||
}
|
||||
|
||||
$this->keepMovement = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z);
|
||||
|
||||
$moveVector = new Vector3($this->x + $this->motionX, $this->y + $this->motionY, $this->z + $this->motionZ);
|
||||
|
||||
$list = $this->getLevel()->getCollidingEntities($this->boundingBox->addCoord($this->motionX, $this->motionY, $this->motionZ)->expand(1, 1, 1), $this);
|
||||
|
||||
$nearDistance = PHP_INT_MAX;
|
||||
$nearEntity = null;
|
||||
|
||||
foreach($list as $entity){
|
||||
if(/*!$entity->canCollideWith($this) or */
|
||||
($entity === $this->shootingEntity and $this->ticksLived < 5)
|
||||
){
|
||||
continue;
|
||||
}
|
||||
|
||||
$axisalignedbb = $entity->boundingBox->grow(0.3, 0.3, 0.3);
|
||||
$ob = $axisalignedbb->calculateIntercept($this, $moveVector);
|
||||
|
||||
if($ob === null){
|
||||
continue;
|
||||
}
|
||||
|
||||
$distance = $this->distance($ob->hitVector);
|
||||
|
||||
if($distance < $nearDistance){
|
||||
$nearDistance = $distance;
|
||||
$nearEntity = $entity;
|
||||
}
|
||||
}
|
||||
|
||||
if($nearEntity !== null){
|
||||
$movingObjectPosition = MovingObjectPosition::fromEntity($nearEntity);
|
||||
}
|
||||
|
||||
if($movingObjectPosition !== null){
|
||||
if($movingObjectPosition->entityHit !== null){
|
||||
|
||||
$this->server->getPluginManager()->callEvent(new ProjectileHitEvent($this));
|
||||
|
||||
$motion = sqrt($this->motionX ** 2 + $this->motionY ** 2 + $this->motionZ ** 2);
|
||||
$damage = ceil($motion * $this->damage);
|
||||
|
||||
if($this->shootingEntity === null){
|
||||
$ev = new EntityDamageByEntityEvent($this, $movingObjectPosition->entityHit, EntityDamageEvent::CAUSE_PROJECTILE, $damage);
|
||||
}else{
|
||||
$ev = new EntityDamageByChildEntityEvent($this->shootingEntity, $this, $movingObjectPosition->entityHit, EntityDamageEvent::CAUSE_PROJECTILE, $damage);
|
||||
}
|
||||
|
||||
$movingObjectPosition->entityHit->attack($ev->getFinalDamage(), $ev);
|
||||
|
||||
|
||||
if($this->fireTicks > 0){
|
||||
$ev = new EntityCombustByEntityEvent($this, $movingObjectPosition->entityHit, 5);
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
if(!$ev->isCancelled()){
|
||||
$movingObjectPosition->entityHit->setOnFire($ev->getDuration());
|
||||
}
|
||||
}
|
||||
|
||||
$this->kill();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
|
||||
if($this->isCollided and !$this->hadCollision){
|
||||
$this->hadCollision = true;
|
||||
|
||||
$this->motionX = 0;
|
||||
$this->motionY = 0;
|
||||
$this->motionZ = 0;
|
||||
|
||||
$this->server->getPluginManager()->callEvent(new ProjectileHitEvent($this));
|
||||
}elseif(!$this->isCollided and !$this->hadCollision){
|
||||
$this->hadCollision = false;
|
||||
}
|
||||
|
||||
if(!$this->onGround or $this->motionX != 0 or $this->motionY != 0 or $this->motionZ != 0){
|
||||
$f = sqrt(($this->motionX ** 2) + ($this->motionZ ** 2));
|
||||
$this->yaw = (atan2($this->motionX, $this->motionZ) * 180 / M_PI);
|
||||
$this->pitch = (atan2($this->motionY, $f) * 180 / M_PI);
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
$this->updateMovement();
|
||||
|
||||
}
|
||||
|
||||
return $hasUpdate;
|
||||
}
|
||||
|
||||
}
|
@ -22,10 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Sheep extends Animal implements Colorable{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Sheep");
|
||||
}
|
||||
|
||||
}
|
@ -22,10 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Silverfish extends Monster{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Silverfish");
|
||||
}
|
||||
|
||||
}
|
@ -21,10 +21,6 @@
|
||||
|
||||
namespace pocketmine\entity;
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Skeleton extends Monster implements ProjectileSource{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Chicken");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,10 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Slime extends Living{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Slime");
|
||||
}
|
||||
|
||||
}
|
@ -22,10 +22,62 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\level\format\FullChunk;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\network\protocol\AddEntityPacket;
|
||||
use pocketmine\network\protocol\SetEntityMotionPacket;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Snowball extends Projectile{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Snowball");
|
||||
const NETWORK_ID = 81;
|
||||
|
||||
public $width = 0.25;
|
||||
public $length = 0.25;
|
||||
public $height = 0.25;
|
||||
|
||||
protected $gravity = 0.03;
|
||||
protected $drag = 0.01;
|
||||
|
||||
public function __construct(FullChunk $chunk, Compound $nbt, Entity $shootingEntity = null){
|
||||
$this->shootingEntity = $shootingEntity;
|
||||
parent::__construct($chunk, $nbt);
|
||||
}
|
||||
|
||||
public function onUpdate($currentTick){
|
||||
if($this->closed){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->timings->startTiming();
|
||||
|
||||
$hasUpdate = parent::onUpdate($currentTick);
|
||||
|
||||
if($this->age > 1200 or $this->isCollided){
|
||||
$this->kill();
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
$this->timings->stopTiming();
|
||||
|
||||
return $hasUpdate;
|
||||
}
|
||||
|
||||
public function spawnTo(Player $player){
|
||||
$pk = new AddEntityPacket();
|
||||
$pk->type = Snowball::NETWORK_ID;
|
||||
$pk->eid = $this->getID();
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
$pk->z = $this->z;
|
||||
$pk->did = 0; //TODO: send motion here
|
||||
$player->dataPacket($pk);
|
||||
|
||||
$pk = new SetEntityMotionPacket();
|
||||
$pk->entities = [
|
||||
[$this->getID(), $this->motionX, $this->motionY, $this->motionZ]
|
||||
];
|
||||
$player->dataPacket($pk);
|
||||
|
||||
parent::spawnTo($player);
|
||||
}
|
||||
}
|
@ -22,10 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Spider extends Monster{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Spider");
|
||||
}
|
||||
|
||||
}
|
@ -23,7 +23,6 @@ namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\Int;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\network\protocol\AddMobPacket;
|
||||
use pocketmine\network\protocol\SetEntityMotionPacket;
|
||||
use pocketmine\Player;
|
||||
@ -48,7 +47,6 @@ class Villager extends Creature implements NPC, Ageable{
|
||||
|
||||
protected function initEntity(){
|
||||
parent::initEntity();
|
||||
$this->namedtag->id = new String("id", "Villager");
|
||||
if(!isset($this->namedtag->Profession)){
|
||||
$this->setProfession(self::PROFESSION_GENERIC);
|
||||
}
|
||||
|
@ -22,10 +22,6 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\nbt\tag\String;
|
||||
|
||||
class Wolf extends Animal implements Tameable{
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Wolf");
|
||||
}
|
||||
|
||||
}
|
@ -23,8 +23,7 @@ namespace pocketmine\entity;
|
||||
|
||||
|
||||
use pocketmine\event\entity\EntityDamageByEntityEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\item\Item as ItemItem;
|
||||
use pocketmine\network\protocol\AddMobPacket;
|
||||
use pocketmine\network\protocol\SetEntityMotionPacket;
|
||||
use pocketmine\Player;
|
||||
@ -36,10 +35,6 @@ class Zombie extends Monster{
|
||||
public $length = 0.6;
|
||||
public $height = 1.8;
|
||||
|
||||
protected function initEntity(){
|
||||
$this->namedtag->id = new String("id", "Zombie");
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
return "Zombie";
|
||||
}
|
||||
@ -83,19 +78,19 @@ class Zombie extends Monster{
|
||||
|
||||
public function getDrops(){
|
||||
$drops = [
|
||||
Item::get(Item::FEATHER, 0, 1)
|
||||
ItemItem::get(ItemItem::FEATHER, 0, 1)
|
||||
];
|
||||
if($this->lastDamageCause instanceof EntityDamageByEntityEvent and $this->lastDamageCause->getEntity() instanceof Player){
|
||||
if(mt_rand(0, 199) < 5){
|
||||
switch(mt_rand(0, 2)){
|
||||
case 0:
|
||||
$drops[] = Item::get(Item::IRON_INGOT, 0, 1);
|
||||
$drops[] = ItemItem::get(ItemItem::IRON_INGOT, 0, 1);
|
||||
break;
|
||||
case 1:
|
||||
$drops[] = Item::get(Item::CARROT, 0, 1);
|
||||
$drops[] = ItemItem::get(ItemItem::CARROT, 0, 1);
|
||||
break;
|
||||
case 2:
|
||||
$drops[] = Item::get(Item::POTATO, 0, 1);
|
||||
$drops[] = ItemItem::get(ItemItem::POTATO, 0, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ abstract class Event{
|
||||
* Any callable event must declare the static variable
|
||||
*
|
||||
* public static $handlerList = null;
|
||||
* public static $eventPool = [];
|
||||
* public static $nextEvent = 0;
|
||||
*
|
||||
* Not doing so will deny the proper event initialization
|
||||
*/
|
||||
@ -41,7 +43,7 @@ abstract class Event{
|
||||
* @return string
|
||||
*/
|
||||
final public function getEventName(){
|
||||
return $this->eventName !== null ? get_class($this) : $this->eventName;
|
||||
return $this->eventName === null ? get_class($this) : $this->eventName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,7 +90,7 @@ class HandlerList{
|
||||
return;
|
||||
}
|
||||
if(isset($this->handlerSlots[$listener->getPriority()][spl_object_hash($listener)])){
|
||||
throw new \Exception("This listener is already registered to priority " . $listener->getPriority());
|
||||
throw new \InvalidStateException("This listener is already registered to priority " . $listener->getPriority());
|
||||
}
|
||||
$this->handlers = null;
|
||||
$this->handlerSlots[$listener->getPriority()][spl_object_hash($listener)] = $listener;
|
||||
|
@ -56,6 +56,11 @@ class LevelTimings{
|
||||
/** @var TimingsHandler */
|
||||
public $tickEntities;
|
||||
|
||||
/** @var TimingsHandler */
|
||||
public $syncChunkSendTimer;
|
||||
/** @var TimingsHandler */
|
||||
public $syncChunkSendPrepareTimer;
|
||||
|
||||
/** @var TimingsHandler */
|
||||
public $syncChunkLoadTimer;
|
||||
/** @var TimingsHandler */
|
||||
@ -87,6 +92,9 @@ class LevelTimings{
|
||||
$this->tileEntityTick = new TimingsHandler("** " . $name . "tileEntityTick");
|
||||
$this->tileEntityPending = new TimingsHandler("** " . $name . "tileEntityPending");
|
||||
|
||||
$this->syncChunkSendTimer = new TimingsHandler("** " . $name . "syncChunkSend");
|
||||
$this->syncChunkSendPrepareTimer = new TimingsHandler("** " . $name . "syncChunkSendPrepare");
|
||||
|
||||
$this->syncChunkLoadTimer = new TimingsHandler("** " . $name . "syncChunkLoad");
|
||||
$this->syncChunkLoadDataTimer = new TimingsHandler("** " . $name . "syncChunkLoad - Data");
|
||||
$this->syncChunkLoadStructuresTimer = new TimingsHandler("** " . $name . "syncChunkLoad - Structures");
|
||||
|
@ -28,6 +28,8 @@ use pocketmine\Player;
|
||||
|
||||
class BlockBreakEvent extends BlockEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
/** @var \pocketmine\Player */
|
||||
protected $player;
|
||||
|
@ -26,6 +26,8 @@ use pocketmine\event\Cancellable;
|
||||
|
||||
class BlockFormEvent extends BlockGrowEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
public function __construct(Block $block, Block $newState){
|
||||
parent::__construct($block, $newState);
|
||||
|
@ -26,6 +26,8 @@ use pocketmine\event\Cancellable;
|
||||
|
||||
class BlockGrowEvent extends BlockEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
/** @var Block */
|
||||
private $newState;
|
||||
|
@ -31,6 +31,8 @@ use pocketmine\Player;
|
||||
*/
|
||||
class BlockPlaceEvent extends BlockEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
/** @var \pocketmine\Player */
|
||||
protected $player;
|
||||
|
@ -26,6 +26,8 @@ use pocketmine\event\Cancellable;
|
||||
|
||||
class BlockSpreadEvent extends BlockFormEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
/** @var Block */
|
||||
private $source;
|
||||
|
@ -21,14 +21,14 @@
|
||||
|
||||
namespace pocketmine\event\block;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\event\Cancellable;
|
||||
use pocketmine\Player;
|
||||
|
||||
/**
|
||||
* Called when a block tries to be updated due to a neighbor change
|
||||
*/
|
||||
class BlockUpdateEvent extends BlockEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
}
|
@ -26,6 +26,8 @@ use pocketmine\event\Cancellable;
|
||||
|
||||
class LeavesDecayEvent extends BlockEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
public function __construct(Block $block){
|
||||
parent::__construct($block);
|
||||
|
@ -30,6 +30,8 @@ use pocketmine\Player;
|
||||
*/
|
||||
class SignChangeEvent extends BlockEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
/** @var \pocketmine\Player */
|
||||
private $player;
|
||||
|
@ -28,6 +28,8 @@ use pocketmine\item\Item;
|
||||
|
||||
class EntityArmorChangeEvent extends EntityEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
private $oldItem;
|
||||
private $newItem;
|
||||
|
@ -30,6 +30,8 @@ use pocketmine\event\Cancellable;
|
||||
*/
|
||||
class EntityBlockChangeEvent extends EntityEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
private $from;
|
||||
private $to;
|
||||
|
@ -25,6 +25,8 @@ use pocketmine\block\Block;
|
||||
use pocketmine\entity\Entity;
|
||||
|
||||
class EntityCombustByBlockEvent extends EntityCombustEvent{
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
protected $combuster;
|
||||
|
||||
|
@ -24,6 +24,8 @@ namespace pocketmine\event\entity;
|
||||
use pocketmine\entity\Entity;
|
||||
|
||||
class EntityCombustByEntityEvent extends EntityCombustEvent{
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
protected $combuster;
|
||||
|
||||
|
@ -26,6 +26,8 @@ use pocketmine\event\Cancellable;
|
||||
|
||||
class EntityCombustEvent extends EntityEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
protected $duration;
|
||||
|
||||
|
@ -25,6 +25,8 @@ use pocketmine\block\Block;
|
||||
use pocketmine\entity\Entity;
|
||||
|
||||
class EntityDamageByBlockEvent extends EntityDamageEvent{
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
/** @var Block */
|
||||
private $damager;
|
||||
|
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\event\entity;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
|
||||
class EntityDamageByChildEntityEvent extends EntityDamageByEntityEvent{
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
/** @var Entity */
|
||||
private $childEntity;
|
||||
|
||||
|
||||
/**
|
||||
* @param Entity $damager
|
||||
* @param Entity $childEntity
|
||||
* @param Entity $entity
|
||||
* @param int $cause
|
||||
* @param int|int[] $damage
|
||||
*/
|
||||
public function __construct(Entity $damager, Entity $childEntity, Entity $entity, $cause, $damage){
|
||||
$this->childEntity = $childEntity;
|
||||
parent::__construct($damager, $entity, $cause, $damage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Entity
|
||||
*/
|
||||
public function getChild(){
|
||||
return $this->childEntity;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -24,6 +24,8 @@ namespace pocketmine\event\entity;
|
||||
use pocketmine\entity\Entity;
|
||||
|
||||
class EntityDamageByEntityEvent extends EntityDamageEvent{
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
/** @var Entity */
|
||||
private $damager;
|
||||
|
@ -26,6 +26,8 @@ use pocketmine\event\Cancellable;
|
||||
|
||||
class EntityDamageEvent extends EntityEvent implements Cancellable{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
const MODIFIER_BASE = 0;
|
||||
const MODIFIER_ARMOR = 1;
|
||||
@ -74,7 +76,7 @@ class EntityDamageEvent extends EntityEvent implements Cancellable{
|
||||
$this->originals = $this->modifiers;
|
||||
|
||||
if(!isset($this->modifiers[self::MODIFIER_BASE])){
|
||||
throw new \Exception("BASE Damage modifier missing");
|
||||
throw new \InvalidArgumentException("BASE Damage modifier missing");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,8 @@ use pocketmine\item\Item;
|
||||
|
||||
class EntityDeathEvent extends EntityEvent{
|
||||
public static $handlerList = null;
|
||||
public static $eventPool = [];
|
||||
public static $nextEvent = 0;
|
||||
|
||||
/** @var Item[] */
|
||||
private $drops = [];
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user