Compare commits

..

167 Commits

Author SHA1 Message Date
c7f578f297 Possible fix for #2297 2014-11-18 13:57:03 +01:00
19c030281f Fixed #1969 2014-11-18 13:53:38 +01:00
ca9fe1b89a Improved and fixed command exception message, closes #2301 2014-11-18 13:46:00 +01:00
9fd6a695f6 Fixed permission-related memory leak 2014-11-18 13:42:24 +01:00
c07b0ff35b Fixed tile entities not being placed in the correct array 2014-11-15 11:49:09 +01:00
6796fca2b6 Merge pull request #2294 from LukeDarling/patch-1
fixed version message color
2014-11-15 14:20:14 +10:30
5657cce3db fixed version message color 2014-11-14 15:52:38 -05:00
05ac256cc3 Fixed Acacia / Dark Oak logs crafting recipes 2014-11-14 15:58:31 +01:00
49977c5410 Bumped weakref version, fixes travis builds 2014-11-14 10:30:06 +01:00
ca40bb678c Merge pull request #2288 from sekjun9878/master
Get timezone directly. Fixes #2287.
2014-11-13 23:08:22 +10:30
2068cc9cdf Merge pull request #2243 from PEMapModder/patch-1
cmd files comment syntax should be like this.
2014-11-13 21:42:25 +10:30
ea4617cedd Get timezone directly. Fixes #2287. 2014-11-13 21:13:12 +10:30
1a5544f68c Fixed Chunk tile indexes 2014-11-08 15:00:18 +01:00
0128a7aeb2 API version 1.7.1 (fixes) 2014-11-07 09:45:30 +01:00
fd954ce708 Fixed PlayerInventory->setItem() with null items 2014-11-07 09:43:36 +01:00
d63a82de0a MCPE protocol 20 2014-11-06 19:08:32 +01:00
92143d523c Added SetDifficultyPacket 2014-11-06 19:07:24 +01:00
1818e64c8e Merge branch 'master' into 0.10 2014-11-06 18:56:47 +01:00
7e1095e28d Reenabled collision against entities on move 2014-11-06 12:57:17 +01:00
f1519e6d13 Improved Level->getTile() to a direct lookup instead of linear search 2014-11-06 12:34:33 +01:00
3b9a9bcd5d Use proper indexes on Living->getLineOfSight() when a max length is set 2014-11-06 12:23:45 +01:00
263bff01c8 Change RuntimeException to InvalidStateException on BlockIterator 2014-11-06 12:16:12 +01:00
987d647b76 Return proper BlockIterator index, throw more exceptions, improved blockQueue performance 2014-11-06 12:12:31 +01:00
522b75645c Merge branch 'master' into 0.10 2014-11-05 19:04:36 +01:00
9eed0a579c Fixed red sand smelting recipe 2014-11-05 17:41:12 +01:00
064976d32b Fixed ladder recipe 2014-11-05 17:38:23 +01:00
2abb577178 Fixed String -> Wool recipe 2014-11-05 17:36:44 +01:00
127855c220 Fixed Snow block recipe 2014-11-05 17:36:06 +01:00
93c7a3c170 Fixed bonemeal recipe, closes #2260 2014-11-05 17:32:28 +01:00
31903a764a Fixed unloaded chunks residing on memory and getting loaded again causing crash, fixed spawn chunks getting unloaded by players 2014-11-04 17:16:02 +01:00
79bc1d6c85 Fixed server not stopping after a special crash 2014-11-04 17:15:20 +01:00
cc7f12739d Added vertical and horizontal collision detection to Entities 2014-11-04 12:23:42 +01:00
32dae93ef9 Removed unused imports 2014-11-04 12:08:24 +01:00
8fd6582e74 Automatically set Entity / Tile entity save identifiers 2014-11-04 12:04:08 +01:00
a5369b3570 Fixed unloading chunks 2014-11-04 11:18:34 +01:00
abbd33210a Possible fix for #2245 2014-11-04 00:19:50 +01:00
6b6222c09c Allow passing a Player source as last parameter on Inventory->addItem() and Inventory->removeItem() 2014-11-04 00:16:25 +01:00
a8c997d88a ¬¬ 2014-11-03 12:54:46 +01:00
6993718a83 Added EntityDamageByChildEntityEvent 2014-11-03 12:03:37 +01:00
86afecec89 Improved inventory sending, send single slots instead of full inventory as much as possible 2014-11-03 11:48:10 +01:00
29d1fd1fc8 Fixed player viewer list including themselves 2014-11-03 11:29:01 +01:00
af4eb2ab1e Create server.log properly on non-existent directories 2014-11-02 16:15:15 +01:00
f7baf46a54 Fire PlayerInteractEvent on 0xff face 2014-11-02 16:12:51 +01:00
75c0d8324c Fixed some inventory events not firing on players 2014-11-02 13:26:58 +01:00
da4334f06b Revert Armor then Inventory instead of Inventory then Armor on failed transaction 2014-11-01 23:02:59 +01:00
413bd3c0df Use SplFixedArray for improved performance 2014-11-01 22:12:35 +01:00
1a0428654b Updated timings command, give direct link to results 2014-11-01 21:20:44 +01:00
2803a38fd1 Fixed random block updates not firing 2014-11-01 20:26:13 +01:00
95a5ca7889 Added command message to /time add 2014-11-01 20:12:55 +01:00
240f14c425 Fixed #2253 2014-11-01 19:40:15 +01:00
cb9b6ab1d1 Fixed server not using the correct provided path if it did not exist 2014-11-01 19:23:10 +01:00
8a87280566 Added /time start and /time stop 2014-11-01 17:45:11 +01:00
4d97827d44 Improved level switching for players 2014-11-01 17:39:09 +01:00
f8f1e0e9df Despawn entities correctly from clients as they move 2014-11-01 16:47:40 +01:00
bf596ebf05 Fixed Query-related crash 2014-11-01 16:20:40 +01:00
90777014b6 Fixed Stone crash 2014-11-01 16:17:47 +01:00
4a78ffd2dd Fixed FallingSand crash 2014-11-01 16:15:09 +01:00
7c361a52d2 Fixed #2252 2014-11-01 13:52:20 +01:00
13fc0df92c Fixed #2251 2014-11-01 12:40:45 +01:00
d5012f6fcf Fixed server not stopping after a fatal error 2014-11-01 03:07:47 +01:00
4569a73f3d Fixed Entity being set position after being closed 2014-10-31 23:10:29 +01:00
66acb5cdd7 Possible fix for crashing server not stopping 2014-10-31 23:10:12 +01:00
8601405a88 Fixed CPU leak 2014-10-31 21:07:00 +01:00
ae06681b60 Added packet exception handling, updated RakLib 2014-10-31 19:14:59 +01:00
01ffb14e39 Fixed #2204 2014-10-31 17:34:45 +01:00
ce989876af Improved freeing chunks 2014-10-31 16:39:32 +01:00
f8d6ebabf3 Removed some calls 2014-10-31 15:57:07 +01:00
094b600a0c Updated NBT/DataPacket reading 2014-10-31 01:02:31 +01:00
82cfe6ea9c Updated NBT/DataPacket reading 2014-10-31 00:32:50 +01:00
4fba6d7c86 Merge branch 'master' into 0.10 2014-10-30 23:20:59 +01:00
f72d7284b9 Added EncapsulatedPacket reuse on broadcast 2014-10-30 23:20:28 +01:00
8f0527832f Removed extra AxisAlignedBB generation on Door and Trapdoor 2014-10-30 22:15:19 +01:00
f66944368d Update RakLib 2014-10-30 22:06:23 +01:00
7ab3c57b00 Optimized networking code & AxisAlignedBB 2014-10-30 22:06:07 +01:00
673b867ee8 Fixed players not loading chunks when stuck on a unloaded chunk 2014-10-30 20:05:40 +01:00
2424c8a76c Update RakLib, possible fix for notifyACK 2014-10-30 19:44:05 +01:00
92eb5cb0b8 Added LE Triad methods 2014-10-30 17:56:58 +01:00
fd46c71120 Updated RakLib 2014-10-30 17:18:43 +01:00
6a4259bf24 Updated RakLib 2014-10-30 17:04:19 +01:00
9a65279c6a Added ifndef for packets Binary 2014-10-30 16:41:11 +01:00
09a01be709 Added ifndef for NBT Binary 2014-10-30 16:32:57 +01:00
57d1847c50 Updated to receive new optimizations 2014-10-30 16:02:48 +01:00
6e8e2a79dd Fixed Event name being null 2014-10-30 14:52:11 +01:00
d8f9def7f4 Added preprocessor optimizations 2014-10-30 07:58:53 +01:00
8cb9dd9a14 Fixed #2244 2014-10-29 22:58:40 +01:00
c4c374e3fa Added extra chunk sending timings 2014-10-29 21:52:27 +01:00
d57e37896d Improved Region / RakLib 2014-10-29 17:43:21 +01:00
022a978ffb Added InventoryPickupArrowEvent 2014-10-29 16:29:00 +01:00
00b282d40c Improved cache pool cleanup times 2014-10-29 16:13:47 +01:00
8a768cea33 EntityDamageEvent and children now only fire if the attack is possible, moved event trigger to Entity->attack() 2014-10-29 16:02:40 +01:00
289bc56b4b Blocks now save their bounding box, fixed entity block collision check 2014-10-29 15:43:23 +01:00
6f64af3066 Reuse even more objects! 2014-10-29 14:23:51 +01:00
72c09045d5 Fixed Zombie drops crash 2014-10-29 13:21:54 +01:00
5e55c3a8f0 Fixed Chest->unpair() 2014-10-29 13:21:14 +01:00
afaa2cf722 Fixed Double Chest behavior 2014-10-29 12:57:26 +01:00
50cfeaa393 Fixed Stonecutter recipe 2014-10-29 12:36:34 +01:00
dda8b03349 Fixed Bowl recipe 2014-10-29 12:12:54 +01:00
56e848488a Fixed Trapdoor recipe 2014-10-29 12:10:48 +01:00
7e4f862634 Fixed typo in OfflinePlayer 2014-10-29 11:42:29 +01:00
577a7a1c3d cmd files comment syntax should be like this. 2014-10-29 17:20:36 +08:00
78f8d0280d Removed unused imports 2014-10-29 01:14:09 +01:00
0680b98380 Remove chunks from advanced cache after setting 2014-10-29 01:07:30 +01:00
cbe0fe5e46 Added Entity->onGround setting when entities keep moving without checks 2014-10-29 00:41:13 +01:00
7eed92e8fb Use Player->forceMovement on MovePlayerPacket non-tick revert 2014-10-29 00:31:17 +01:00
f772391866 Fixed InventoryPickupItemEvent 2014-10-28 22:05:54 +01:00
8c4faa8622 Added extra Exceptions 2014-10-28 21:07:12 +01:00
b6f7ee20fc Added Error -> Exception handling 2014-10-28 20:43:36 +01:00
0fce83c671 Fixed #2189 2014-10-28 13:27:30 +01:00
8080643cc9 Fixed plugins crashing the server when teleporting players on an invalid event 2014-10-28 13:18:40 +01:00
5bf2174cad Fixed UseItemPacket being able to be sent before spawning 2014-10-28 13:16:20 +01:00
34ae760def New way to spawn entities/tiles using a global register table, allow overriding default entity/tile classes via classes 2014-10-28 13:09:27 +01:00
a5b85c549a Added Snowballs 2014-10-28 12:13:31 +01:00
b9f1812f61 Disallow further modification of Signs by its creator after load/unload 2014-10-28 11:05:32 +01:00
350cee3d41 Added Event allocation pool, updated SPL with Class::onClassLoaded() 2014-10-28 10:47:40 +01:00
144a871c07 Improved Vector3 and Block handling, less allocation on Positions 2014-10-28 10:03:10 +01:00
69492474e4 Improve #2238, do not crash when an invalid/corrupt RCON stop event happens 2014-10-28 02:09:36 +01:00
4299ebebcc Bump API version to 1.6.1 2014-10-28 00:55:07 +01:00
119b429ab8 RakLib update 2014-10-28 00:43:47 +01:00
8f1eb41ca5 RakLib update 2014-10-28 00:23:55 +01:00
ca92d2a0d3 Bumped API version to 1.7.0 2014-10-27 20:30:58 +01:00
db82f76c11 Improved network packets allocation 2014-10-27 20:30:33 +01:00
3f5b129cf5 Updated RakLib 2014-10-27 19:39:24 +01:00
f6aac8728b Mark chunk to be saved when removing invalid entities/tiles 2014-10-27 18:43:58 +01:00
809fc44813 Bump API version to 1.6.1 2014-10-27 16:07:00 +01:00
64f1ff066d Fixed /setworldspawn changing sender data 2014-10-27 15:57:26 +01:00
a5a3f4801a Fixed entities not getting ticks on movement 2014-10-27 15:53:14 +01:00
23d1532ff9 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-10-27 15:44:44 +01:00
ecbbcc2e8e Drop invalid entities / tile entities on chunk loading 2014-10-27 15:44:36 +01:00
7abf52e615 Implemented Vector3 List and AxisAlignedBB Pool to decrease object allocation 2014-10-27 15:39:20 +01:00
9e01e2ef49 Merge pull request #2235 from nno88551/patch-2
Update BaseInventory.php
2014-10-26 15:52:08 +01:00
df81b365e5 Update BaseInventory.php 2014-10-26 22:21:21 +09:00
db8ac0b9cb Merge pull request #2225 from PEMapModder/falling-sand
Update FallingBlock to new Anvil formats, possible fix for #2189
2014-10-25 17:58:47 +02:00
ee4f416d93 Fix FallingBlock.php 2014-10-25 18:15:47 +08:00
8feea721e3 Merge pull request #2223 from Falkirks/set-armour-fix
Fix various get and set armour in PlayerInventory
2014-10-25 12:13:28 +02:00
8e7077ff4b Update FallingBlock to new Anvil formats, possible fix for #2189
I don't have time to test yet, so I am not sure if it does fix it.
2014-10-25 12:26:57 +08:00
4f4a6e7446 Fixes get and set armour 2014-10-24 17:11:59 -07:00
1fc066fc37 Updated time steps from x2.5 to x1.25 2014-10-24 12:12:01 +02:00
b565844062 Merge branch 'master' into 0.10 2014-10-24 12:07:35 +02:00
be948f99cc Fixed #2207 Server crashing if players are closed before logging in 2014-10-24 12:06:55 +02:00
5cb428e5cc Updated build number 2014-10-23 17:23:59 +02:00
d2f4a14d66 Merge branch 'master' into 0.10 2014-10-23 17:21:24 +02:00
516bb37a50 Removed some direct type checks on Entity/Tile->closed 2014-10-21 19:28:29 +02:00
580ade9092 Possible fix for entities not closing correctly 2014-10-21 19:26:16 +02:00
8f7dfe0b71 Removed extra ; from if, fixes #2205 2014-10-21 18:37:29 +02:00
5310ba3ae6 Fixed crash when doing var_dump() of anything that contains the Server object 2014-10-20 13:06:53 +02:00
ef97efcd96 Added explosion death message 2014-10-20 13:00:03 +02:00
30c3718ea8 Improved Explosion item drop position 2014-10-20 12:58:05 +02:00
5437567e95 Merge branch 'master' into 0.10 2014-10-20 12:53:14 +02:00
e3e97a4205 Improved Player->onGround checking 2014-10-20 12:52:00 +02:00
fec387d2ec Fixed entities not being pushed out of blocks 2014-10-20 12:37:17 +02:00
481e2b08ee Removed debug call 2014-10-20 12:05:40 +02:00
15de0eece7 Improved inventory and window allocation, fixes #2200 2014-10-20 09:48:11 +02:00
2f8267aa1e Improved Level object deallocation 2014-10-19 20:45:03 +02:00
f2b573c32f Fixed Level->getMetadata() and similar, removed extra references 2014-10-19 19:51:36 +02:00
34946faf94 Remove errors from Utils::getRandomBytes() 2014-10-19 13:44:38 +02:00
3b47513439 Return result directly on Server->getOfflinePlayer() 2014-10-19 02:49:58 +02:00
7d9a98ec6b Updated UseItemPacket 2014-10-18 23:42:41 +02:00
92facc94b9 Added new fences and fence gates to fuel types 2014-10-18 18:02:39 +02:00
d3327f450c Added different Fence Gates, new Fence Gate crafting recipes 2014-10-18 17:56:18 +02:00
570cab9c66 Added different Fences, new Fence crafting recipes 2014-10-18 17:44:24 +02:00
582ba100b0 Bumped protocol version to 19 2014-10-18 17:01:36 +02:00
4c0daa462d Merge branch 'master' into 0.10 2014-10-18 16:54:03 +02:00
2e6366868d Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-10-18 16:53:42 +02:00
245e9b4f18 Fixes inventory changes getting the wrong window, closes #2187 2014-10-18 16:53:06 +02:00
68e73d4e3a Merge pull request #2188 from aodzip/patch-1
Update Skeleton.php
2014-10-18 15:36:02 +02:00
684617d370 Update Skeleton.php
fixed a little wrong
2014-10-18 21:13:35 +08:00
a879104a6f Minecraft: PE version bump 2014-10-17 14:43:10 +02:00
289 changed files with 3328 additions and 1701 deletions

View File

@ -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

View File

@ -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",

View File

@ -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{
}
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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,

View File

@ -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){

View File

@ -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){

View File

@ -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,

View File

@ -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,

View File

@ -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());

View File

@ -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;

View File

@ -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,

View File

@ -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;
}
}
}

View File

@ -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,

View File

@ -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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View File

@ -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,

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View File

@ -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);

View File

@ -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()){

View File

@ -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,

View File

@ -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){

View File

@ -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()){

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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],
];

View File

@ -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,

View File

@ -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),

View File

@ -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,

View File

@ -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){

View File

@ -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,

View File

@ -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){

View File

@ -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){

View File

@ -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;
}
}
}

View File

@ -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,

View File

@ -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();

View File

@ -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");

View File

@ -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{

View File

@ -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");

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -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]
];

View File

@ -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();

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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){

View File

@ -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;
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}
}

View File

@ -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");
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}

View File

@ -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);
}

View File

@ -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");
}
}

View File

@ -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;
}
}

View File

@ -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;
}
/**

View File

@ -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;

View File

@ -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");

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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");
}
}

View File

@ -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