mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-10 11:38:08 +00:00
Compare commits
197 Commits
Alpha_1.4d
...
Alpha_1.4d
Author | SHA1 | Date | |
---|---|---|---|
45dbb3f828 | |||
8a8a95480e | |||
34139c7efe | |||
f0e7713dce | |||
3ba099b309 | |||
c4a0c759dc | |||
e9a2f88847 | |||
e608acbd1c | |||
42033da08b | |||
69ab0d433b | |||
44a30b7fac | |||
50b2f55583 | |||
da084d6908 | |||
7d51bc0004 | |||
87dbc18452 | |||
5b8d4bba11 | |||
bb4c54106a | |||
1617b2509e | |||
ec293ebd9e | |||
9f9422f0ed | |||
da715e48e2 | |||
702b2e539c | |||
63fc229c12 | |||
c71689a919 | |||
09428bc8c7 | |||
6c7e16d9d4 | |||
315ea2ea3c | |||
83eb9f778a | |||
7923c40b33 | |||
d298adabad | |||
cfcf515f62 | |||
b5deae7ba0 | |||
d991c32435 | |||
dbd1f3f96e | |||
0bd7ab9def | |||
665c275bb7 | |||
7ef2708fca | |||
78b4223795 | |||
0328b4c5f5 | |||
4624dfb472 | |||
fba12c6ddf | |||
60011a5ecf | |||
f4ae58dda2 | |||
8c939feed9 | |||
02ca227085 | |||
1174b0c45c | |||
8940360df4 | |||
bb34e06754 | |||
e06092cb99 | |||
57373b8c5e | |||
317c6788a6 | |||
0a4e0e3228 | |||
d8c492de4a | |||
05d59d587b | |||
7d387fe6aa | |||
4f7a6a06be | |||
344c84cfa6 | |||
bd721a13a3 | |||
92b0b4d43c | |||
d0b0fbf992 | |||
ab334e6962 | |||
1ad6438e60 | |||
4ecec42c9d | |||
84e62598ce | |||
ad7acb93b6 | |||
ac4b4b08fd | |||
d3c308c5a8 | |||
98e0583f34 | |||
020351e20f | |||
f140fef52d | |||
9980a0780a | |||
352497d88c | |||
ba08bfaa45 | |||
dea4513c34 | |||
0eac084aa7 | |||
e17ecf5795 | |||
e94ddcabe0 | |||
acf7eb1ce9 | |||
dcfb7a7ac4 | |||
97c87aa8fa | |||
11f684d803 | |||
ff48eb3d4d | |||
e047b6a870 | |||
c5626bae34 | |||
3eac08f5ba | |||
cc2555bb88 | |||
705e4da789 | |||
9b7a94b5ee | |||
bcdb6d8c2e | |||
eff63a661e | |||
5a756d215d | |||
422262d585 | |||
b761a97660 | |||
7579cd763a | |||
6bc5f60011 | |||
3eb8ca0d13 | |||
a23352be88 | |||
fa5f00a1ff | |||
d3a05adede | |||
f9182bd0f8 | |||
edad52c6ea | |||
cd5e16f017 | |||
310a7d6c04 | |||
ccea26c978 | |||
cf542ac73a | |||
3bf39df255 | |||
910e5e6181 | |||
a396b8c220 | |||
ec1fe6a083 | |||
706c97b9b1 | |||
a04516a879 | |||
0f6dfd39b8 | |||
36ee6d9966 | |||
23793e0fc4 | |||
3409d332e7 | |||
ca1b67a675 | |||
f5eed4f12b | |||
7a10f91330 | |||
6477f4f077 | |||
3731e74696 | |||
c774e4c203 | |||
d4907a2688 | |||
793520926b | |||
bf839e821c | |||
7aeacf2705 | |||
fc62c91c90 | |||
98dd7f8c15 | |||
7a1d25617f | |||
69b3ef326b | |||
fadff2cc5b | |||
43a0ef433e | |||
9a1e7ca83c | |||
b9111b6f52 | |||
be70121f3a | |||
e2986992c7 | |||
9fb46d8fe8 | |||
eab86f5f90 | |||
2f2afe2336 | |||
f7de1ede3f | |||
812ae09a06 | |||
e473cd5e67 | |||
9e5e4fb362 | |||
afa98866e0 | |||
90fa40de34 | |||
e6234c4c4d | |||
8f66d03d99 | |||
8e9da9c84e | |||
759d7e2545 | |||
f4b92bcdfc | |||
f7e2d31f0a | |||
e0fc3784ad | |||
bf5630dc0d | |||
472431752b | |||
c40f9f65a5 | |||
f74af12914 | |||
d169734781 | |||
35b86af2af | |||
706bc8e8db | |||
b542c5b9bd | |||
69800c6d79 | |||
ea9fc3c72e | |||
8b90281355 | |||
92cabced97 | |||
cb645fa288 | |||
bda597a71e | |||
d6a0e284e3 | |||
1795c8c5e3 | |||
c3b1b59118 | |||
a0df0a8fff | |||
049103ab7a | |||
84c63c48ca | |||
20e11bd408 | |||
456760b334 | |||
46e502430e | |||
87b800ebb9 | |||
9fdafb87b4 | |||
1fcfef20b0 | |||
6109505786 | |||
764937dda4 | |||
8bf36315ae | |||
1ea0531ec7 | |||
c47e359262 | |||
f0f9bccb4b | |||
214dcef1ea | |||
4edadd764c | |||
01ebe74974 | |||
84ce5f1c73 | |||
93a2bd36e0 | |||
fdd59e4506 | |||
9b86b1d45b | |||
1a38003bc4 | |||
60ea4d0e96 | |||
6077190a62 | |||
57299b9a29 | |||
bb08da701b | |||
ee593fe5e4 | |||
e8b1b0fab6 |
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -6,3 +6,6 @@
|
||||
path = src/raklib
|
||||
url = https://github.com/PocketMine/RakLib.git
|
||||
branch = master
|
||||
[submodule "src/spl"]
|
||||
path = src/spl
|
||||
url = https://github.com/PocketMine/PocketMine-SPL.git
|
||||
|
5
.mailmap
Normal file
5
.mailmap
Normal file
@ -0,0 +1,5 @@
|
||||
Shoghi Cervantes <shoghicp@gmail.com>
|
||||
Shoghi Cervantes <shoghicp@gmail.com> Shoghi Cervantes <shoghicp@pocketmine.net>
|
||||
Brandon V <brandon15811@gmail.com>
|
||||
Michael Yoo <sekjun9878@gmail.com> Michael Yoo <michael@yoo.id.au>
|
||||
Michael Yoo <sekjun9878@gmail.com> Michael Yoo <sekjun9878@sekjun9878.info>
|
16
.travis.yml
16
.travis.yml
@ -1,23 +1,21 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
|
||||
branches:
|
||||
except:
|
||||
- Core-Rewrite
|
||||
- master
|
||||
- 0.9.0
|
||||
- master
|
||||
|
||||
before_script:
|
||||
- pecl install channel://pecl.php.net/pthreads-2.0.4
|
||||
- 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.8
|
||||
- pecl install channel://pecl.php.net/weakref-0.2.4
|
||||
- echo | pecl install channel://pecl.php.net/yaml-1.1.1
|
||||
|
||||
script:
|
||||
- php src/tests/ServerSuiteTest.php --no-wizard
|
||||
- php tests/TravisTest.php
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
webhooks: http://n.tkte.ch/h/214/wsNvmG43-ncxUVRrFPwSM-r0
|
||||
#webhooks: http://n.tkte.ch/h/214/wsNvmG43-ncxUVRrFPwSM-r0
|
@ -30,78 +30,78 @@ abstract class Achievement{
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
public static $list = array(
|
||||
public static $list = [
|
||||
/*"openInventory" => array(
|
||||
"name" => "Taking Inventory",
|
||||
"requires" => [],
|
||||
),*/
|
||||
"mineWood" => array(
|
||||
"mineWood" => [
|
||||
"name" => "Getting Wood",
|
||||
"requires" => array( //"openInventory",
|
||||
),
|
||||
),
|
||||
"buildWorkBench" => array(
|
||||
"requires" => [ //"openInventory",
|
||||
],
|
||||
],
|
||||
"buildWorkBench" => [
|
||||
"name" => "Benchmarking",
|
||||
"requires" => array(
|
||||
"requires" => [
|
||||
"mineWood",
|
||||
),
|
||||
),
|
||||
"buildPickaxe" => array(
|
||||
],
|
||||
],
|
||||
"buildPickaxe" => [
|
||||
"name" => "Time to Mine!",
|
||||
"requires" => array(
|
||||
"requires" => [
|
||||
"buildWorkBench",
|
||||
),
|
||||
),
|
||||
"buildFurnace" => array(
|
||||
],
|
||||
],
|
||||
"buildFurnace" => [
|
||||
"name" => "Hot Topic",
|
||||
"requires" => array(
|
||||
"requires" => [
|
||||
"buildPickaxe",
|
||||
),
|
||||
),
|
||||
"acquireIron" => array(
|
||||
],
|
||||
],
|
||||
"acquireIron" => [
|
||||
"name" => "Acquire hardware",
|
||||
"requires" => array(
|
||||
"requires" => [
|
||||
"buildFurnace",
|
||||
),
|
||||
),
|
||||
"buildHoe" => array(
|
||||
],
|
||||
],
|
||||
"buildHoe" => [
|
||||
"name" => "Time to Farm!",
|
||||
"requires" => array(
|
||||
"requires" => [
|
||||
"buildWorkBench",
|
||||
),
|
||||
),
|
||||
"makeBread" => array(
|
||||
],
|
||||
],
|
||||
"makeBread" => [
|
||||
"name" => "Bake Bread",
|
||||
"requires" => array(
|
||||
"requires" => [
|
||||
"buildHoe",
|
||||
),
|
||||
),
|
||||
"bakeCake" => array(
|
||||
],
|
||||
],
|
||||
"bakeCake" => [
|
||||
"name" => "The Lie",
|
||||
"requires" => array(
|
||||
"requires" => [
|
||||
"buildHoe",
|
||||
),
|
||||
),
|
||||
"buildBetterPickaxe" => array(
|
||||
],
|
||||
],
|
||||
"buildBetterPickaxe" => [
|
||||
"name" => "Getting an Upgrade",
|
||||
"requires" => array(
|
||||
"requires" => [
|
||||
"buildPickaxe",
|
||||
),
|
||||
),
|
||||
"buildSword" => array(
|
||||
],
|
||||
],
|
||||
"buildSword" => [
|
||||
"name" => "Time to Strike!",
|
||||
"requires" => array(
|
||||
"requires" => [
|
||||
"buildWorkBench",
|
||||
),
|
||||
),
|
||||
"diamonds" => array(
|
||||
],
|
||||
],
|
||||
"diamonds" => [
|
||||
"name" => "DIAMONDS!",
|
||||
"requires" => array(
|
||||
"requires" => [
|
||||
"acquireIron",
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
|
||||
);
|
||||
];
|
||||
|
||||
|
||||
public static function broadcast(Player $player, $achievementId){
|
||||
@ -120,10 +120,10 @@ abstract class Achievement{
|
||||
|
||||
public static function add($achievementId, $achievementName, array $requires = []){
|
||||
if(!isset(Achievement::$list[$achievementId])){
|
||||
Achievement::$list[$achievementId] = array(
|
||||
Achievement::$list[$achievementId] = [
|
||||
"name" => $achievementName,
|
||||
"requires" => $requires,
|
||||
);
|
||||
];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -19,12 +19,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
interface LoggerAttachment{
|
||||
namespace pocketmine;
|
||||
|
||||
class CompatibleClassLoader extends \BaseClassLoader{
|
||||
|
||||
/**
|
||||
* @param mixed $level
|
||||
* @param string $message
|
||||
* @deprecated
|
||||
*/
|
||||
public function log($level, $message);
|
||||
|
||||
public function add($namespace, $paths){
|
||||
$this->addPath(array_shift($paths));
|
||||
}
|
||||
}
|
@ -43,7 +43,7 @@ class CrashDump{
|
||||
$this->path = $this->server->getDataPath() . "CrashDump_" . date("D_M_j-H.i.s-T_Y", $this->time) . ".log";
|
||||
$this->fp = fopen($this->path, "wb");
|
||||
$this->data["time"] = $this->time;
|
||||
$this->addLine("PocketMine-MP Crash Dump " . date("D M j H:i:s T Y", $this->time));
|
||||
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", $this->time));
|
||||
$this->addLine();
|
||||
$this->baseCrash();
|
||||
$this->generalData();
|
||||
@ -137,7 +137,7 @@ class CrashDump{
|
||||
}else{
|
||||
$error = (array) error_get_last();
|
||||
$error["trace"] = getTrace(4);
|
||||
$errorConversion = array(
|
||||
$errorConversion = [
|
||||
E_ERROR => "E_ERROR",
|
||||
E_WARNING => "E_WARNING",
|
||||
E_PARSE => "E_PARSE",
|
||||
@ -153,7 +153,7 @@ class CrashDump{
|
||||
E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
|
||||
E_DEPRECATED => "E_DEPRECATED",
|
||||
E_USER_DEPRECATED => "E_USER_DEPRECATED",
|
||||
);
|
||||
];
|
||||
$error["fullFile"] = $error["file"];
|
||||
$error["file"] = cleanPath($error["file"]);
|
||||
$error["type"] = isset($errorConversion[$error["type"]]) ? $errorConversion[$error["type"]] : $error["type"];
|
||||
@ -228,7 +228,7 @@ class CrashDump{
|
||||
$this->data["general"]["zend"] = zend_version();
|
||||
$this->data["general"]["php_os"] = PHP_OS;
|
||||
$this->data["general"]["os"] = Utils::getOS();
|
||||
$this->addLine("PocketMine-MP version: " . $version->get(false) . " #" . $version->getNumber() . " [Protocol " . Info::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
|
||||
$this->addLine("PocketMine-MP version: " . $version->get(false) . " #" . $version->getBuild() . " [Protocol " . Info::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
|
||||
$this->addLine("Git commit: " . GIT_COMMIT);
|
||||
$this->addLine("uname -a: " . php_uname("a"));
|
||||
$this->addLine("PHP Version: " . phpversion());
|
||||
|
@ -31,6 +31,7 @@ use pocketmine\entity\Living;
|
||||
use pocketmine\event\block\SignChangeEvent;
|
||||
use pocketmine\event\entity\EntityDamageByEntityEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\event\entity\EntityShootBowEvent;
|
||||
use pocketmine\event\inventory\InventoryCloseEvent;
|
||||
use pocketmine\event\inventory\InventoryPickupItemEvent;
|
||||
use pocketmine\event\player\PlayerAchievementAwardedEvent;
|
||||
@ -59,6 +60,7 @@ use pocketmine\inventory\InventoryHolder;
|
||||
use pocketmine\inventory\SimpleTransactionGroup;
|
||||
use pocketmine\inventory\StonecutterShapelessRecipe;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\format\FullChunk;
|
||||
use pocketmine\level\format\LevelProvider;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\Position;
|
||||
@ -138,7 +140,8 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
protected $isCrafting = false;
|
||||
public $loginData = [];
|
||||
protected $lastMovement = 0;
|
||||
protected $forceMovement = false;
|
||||
/** @var Vector3 */
|
||||
protected $forceMovement = null;
|
||||
protected $connected = true;
|
||||
protected $ip;
|
||||
protected $removeFormat = true;
|
||||
@ -147,9 +150,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
protected $iusername;
|
||||
protected $displayName;
|
||||
protected $startAction = false;
|
||||
/** @var Vector3|bool */
|
||||
protected $sleeping = false;
|
||||
protected $clientID = null;
|
||||
|
||||
protected $stepHeight = 0.5;
|
||||
|
||||
public $usedChunks = [];
|
||||
protected $loadQueue = [];
|
||||
protected $chunkACK = [];
|
||||
@ -687,7 +693,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$chunkZ = $Z + $centerZ;
|
||||
$index = Level::chunkHash($chunkX, $chunkZ);
|
||||
if(!isset($this->usedChunks[$index])){
|
||||
if($this->getLevel()->isChunkPopulated($chunkX, $chunkZ)){
|
||||
if($this->level->isChunkPopulated($chunkX, $chunkZ)){
|
||||
$newOrder[$index] = $distance;
|
||||
}else{
|
||||
$generateQueue->insert([$chunkX, $chunkZ], $distance);
|
||||
@ -728,10 +734,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$entity->despawnFrom($this);
|
||||
}
|
||||
}
|
||||
/*$pk = new UnloadChunkPacket();
|
||||
$pk->chunkX = $X;
|
||||
$pk->chunkZ = $Z;
|
||||
$this->dataPacket($pk);*/
|
||||
|
||||
unset($this->usedChunks[$index]);
|
||||
}
|
||||
}
|
||||
@ -805,11 +808,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
$this->sleeping = $pos;
|
||||
$this->teleport(new Position($pos->x + 0.5, $pos->y + 1, $pos->z + 0.5, $this->getLevel()));
|
||||
/*if($this->entity instanceof Entity){
|
||||
$this->updateMetadata();
|
||||
}*/
|
||||
|
||||
$this->sendMetadata($this->getViewers());
|
||||
$this->sendMetadata($this);
|
||||
|
||||
$this->setSpawn($pos);
|
||||
$this->tasks[] = $this->server->getScheduler()->scheduleDelayedTask(new CallbackTask(array($this, "checkSleep")), 60);
|
||||
$this->tasks[] = $this->server->getScheduler()->scheduleDelayedTask(new CallbackTask([$this, "checkSleep"]), 60);
|
||||
|
||||
|
||||
return true;
|
||||
@ -836,9 +840,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
public function stopSleep(){
|
||||
$this->sleeping = false;
|
||||
//if($this->entity instanceof Entity){
|
||||
//$this->entity->updateMetadata();
|
||||
//}
|
||||
|
||||
$this->sendMetadata($this->getViewers());
|
||||
$this->sendMetadata($this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -848,17 +852,22 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
public function checkSleep(){
|
||||
if($this->sleeping !== false){
|
||||
//TODO: Move to Level
|
||||
/*if($this->server->api->time->getPhase($this->getLevel()) === "night"){
|
||||
|
||||
$time = $this->getLevel()->getTime() % Level::TIME_FULL;
|
||||
|
||||
if($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);{
|
||||
foreach($this->getLevel()->getPlayers() as $p){
|
||||
if($p->sleeping === false){
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->server->api->time->set("day", $this->getLevel());
|
||||
|
||||
$this->getLevel()->setTime($this->getLevel()->getTime() + Level::TIME_FULL - $time);
|
||||
|
||||
foreach($this->getLevel()->getPlayers() as $p){
|
||||
$p->stopSleep();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@ -973,7 +982,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$pk = new StartGamePacket;
|
||||
$pk->seed = $this->getLevel()->getSeed();
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y + 1.62;
|
||||
$pk->y = $this->y + $this->getEyeHeight();
|
||||
$pk->z = $this->z;
|
||||
$pk->spawnX = (int) $spawnPosition->x;
|
||||
$pk->spawnY = (int) $spawnPosition->y;
|
||||
@ -1032,7 +1041,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
0x80000000 ?
|
||||
*/
|
||||
$flags = 0;
|
||||
if(($this->gamemode & 0x02) === 0x02){
|
||||
if($this->isAdventure()){
|
||||
$flags |= 0x01; //Do not allow placing/breaking blocks, adventure mode
|
||||
}
|
||||
|
||||
@ -1045,6 +1054,26 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
|
||||
public function isSurvival(){
|
||||
return ($this->gamemode & 0x01) === 0;
|
||||
}
|
||||
|
||||
public function isCreative(){
|
||||
return ($this->gamemode & 0x01) > 0;
|
||||
}
|
||||
|
||||
public function isAdventure(){
|
||||
return ($this->gamemode & 0x02) > 0;
|
||||
}
|
||||
|
||||
public function getDrops(){
|
||||
if(!$this->isCreative()){
|
||||
return parent::getDrops();
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function getCreativeBlock(Item $item){
|
||||
foreach(Block::$creative as $i => $d){
|
||||
if($d[0] === $item->getID() and $d[1] === $item->getDamage()){
|
||||
@ -1060,13 +1089,13 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
return true;
|
||||
}
|
||||
$hasUpdate = $this->entityBaseTick();
|
||||
foreach($this->getLevel()->getNearbyEntities($this->boundingBox->expand(1, 1, 1), $this) as $entity){
|
||||
foreach($this->getLevel()->getNearbyEntities($this->boundingBox->grow(1, 1, 1), $this) as $entity){
|
||||
if($entity instanceof DroppedItem){
|
||||
if($entity->dead !== true and $entity->getPickupDelay() <= 0){
|
||||
$item = $entity->getItem();
|
||||
|
||||
if($item instanceof Item){
|
||||
if(($this->gamemode & 0x01) === 0 and !$this->inventory->canAddItem($item)){
|
||||
if($this->isSurvival() and !$this->inventory->canAddItem($item)){
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1130,7 +1159,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->displayName = $this->username;
|
||||
$this->nameTag = $this->username;
|
||||
$this->iusername = strtolower($this->username);
|
||||
$this->loginData = array("clientId" => $packet->clientId, "loginData" => $packet->loginData);
|
||||
$this->loginData = ["clientId" => $packet->clientId, "loginData" => $packet->loginData];
|
||||
|
||||
if(count($this->server->getOnlinePlayers()) > $this->server->getMaxPlayers()){
|
||||
if($this->kick("server full") === true){
|
||||
@ -1239,12 +1268,10 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
return;
|
||||
}
|
||||
|
||||
if(($this->gamemode & 0x01) === 0x01){
|
||||
if($this->isCreative()){
|
||||
$this->inventory->setHeldItemSlot(0);
|
||||
$this->inventory->setItemInHand(Item::get(Item::STONE, 0, 1));
|
||||
}else{
|
||||
$this->inventory->setHeldItemSlot(0);
|
||||
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
|
||||
}
|
||||
|
||||
$pk = new LoginStatusPacket;
|
||||
@ -1292,9 +1319,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
|
||||
$this->orderChunks();
|
||||
$this->tasks[] = $this->server->getScheduler()->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "orderChunks")), 10, 40);
|
||||
$this->tasks[] = $this->server->getScheduler()->scheduleDelayedRepeatingTask(new CallbackTask([$this, "orderChunks"]), 10, 40);
|
||||
$this->sendNextChunk();
|
||||
$this->tasks[] = $this->chunkLoadTask = $this->server->getScheduler()->scheduleRepeatingTask(new CallbackTask(array($this, "sendNextChunk")), 1);
|
||||
$this->tasks[] = $this->chunkLoadTask = $this->server->getScheduler()->scheduleRepeatingTask(new CallbackTask([$this, "sendNextChunk"]), 1);
|
||||
|
||||
break;
|
||||
case ProtocolInfo::ROTATE_HEAD_PACKET:
|
||||
@ -1309,44 +1336,73 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
|
||||
$newPos = new Vector3($packet->x, $packet->y, $packet->z);
|
||||
/*if($this->forceMovement instanceof Vector3){
|
||||
if($this->forceMovement->distance($newPos) <= 0.7){
|
||||
$this->forceMovement = false;
|
||||
}else{
|
||||
$this->setPosition($this->forceMovement);
|
||||
}
|
||||
}*/
|
||||
/*$speed = $this->entity->getSpeedMeasure();
|
||||
if($this->blocked === true or ($this->server->api->getProperty("allow-flight") !== true and (($speed > 9 and ($this->gamemode & 0x01) === 0x00) or $speed > 20 or $this->entity->distance($newPos) > 7)) or $this->server->api->handle("player.move", $this->entity) === false){
|
||||
if($this->lastCorrect instanceof Vector3){
|
||||
$this->teleport($this->lastCorrect, $this->entity->yaw, $this->entity->pitch, false);
|
||||
}
|
||||
if($this->blocked !== true){
|
||||
$this->server->getLogger()->warning($this->username." moved too quickly!");
|
||||
}
|
||||
}else{*/
|
||||
$oldPos = new Vector3($this->x, $this->y, $this->z);
|
||||
|
||||
$dy = $newPos->y - $this->y;
|
||||
$revert = false;
|
||||
|
||||
if(count($this->getLevel()->getCollisionBlocks($this->boundingBox->getOffsetBoundingBox(0, $dy - 0.1, 0))) > 0){
|
||||
$isColliding = true;
|
||||
if($this->forceMovement instanceof Vector3 and $newPos->distance($this->forceMovement) > 0.1){
|
||||
$revert = true;
|
||||
}elseif($newPos->distance($this) > 100){
|
||||
$this->server->getLogger()->warning($this->getName()." moved too quickly!");
|
||||
$revert = true;
|
||||
}else{
|
||||
$isColliding = false;
|
||||
if($this->chunk === null or !$this->chunk->isGenerated()){
|
||||
$chunk = $this->getLevel()->getChunkAt($newPos->x >> 4, $newPos->z >> 4);
|
||||
if(!($chunk instanceof FullChunk) or !$chunk->isGenerated()){
|
||||
$revert = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->onGround = ($dy <= 0 and $isColliding);
|
||||
$this->updateFallState($dy, $this->onGround);
|
||||
if(!$revert){
|
||||
$dx = $newPos->x - $this->x;
|
||||
$dy = $newPos->y - $this->y;
|
||||
$dz = $newPos->z - $this->z;
|
||||
|
||||
if(!$this->setPositionAndRotation($newPos, $packet->yaw, $packet->pitch)){
|
||||
$packet->yaw %= 360;
|
||||
$packet->pitch %= 360;
|
||||
|
||||
if($packet->yaw < 0){
|
||||
$packet->yaw += 360;
|
||||
}
|
||||
|
||||
if($packet->pitch < 0){
|
||||
$packet->pitch += 360;
|
||||
}
|
||||
|
||||
$this->setRotation($packet->yaw, $packet->pitch);
|
||||
//$this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z);
|
||||
$revert = !$this->move($dx, $dy, $dz);
|
||||
|
||||
$diffX = $this->x - $newPos->x;
|
||||
$diffZ = $this->z - $newPos->z;
|
||||
$diffY = $this->y - $newPos->y;
|
||||
if($diffY > -0.5 or $diffY < 0.5){
|
||||
$diffY = 0;
|
||||
}
|
||||
|
||||
$diff = $diffX ** 2 + $diffY ** 2 + $diffZ ** 2;
|
||||
|
||||
if(!$revert and $diff > 0.0625 and !$this->isSleeping() and $this->isSurvival()){
|
||||
$revert = true;
|
||||
$this->server->getLogger()->warning($this->getName()." moved wrongly!");
|
||||
}
|
||||
}
|
||||
|
||||
if($revert){
|
||||
$pk = new MovePlayerPacket();
|
||||
$pk->eid = 0;
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y + $this->height; //teleport from head
|
||||
$pk->y = $this->y + $this->getEyeHeight();
|
||||
$pk->z = $this->z;
|
||||
$pk->bodyYaw = $this->yaw;
|
||||
$pk->pitch = $this->pitch;
|
||||
$pk->yaw = $this->yaw;
|
||||
$pk->teleport = true;
|
||||
$this->directDataPacket($pk);
|
||||
$this->forceMovement = new Vector3($this->x, $this->y, $this->z);
|
||||
}else{
|
||||
$this->forceMovement = null;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -1361,7 +1417,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$packet->slot -= 9; //Get real block slot
|
||||
}
|
||||
|
||||
if(($this->gamemode & 0x01) === 1){ //Creative mode match
|
||||
if($this->isCreative()){ //Creative mode match
|
||||
$item = Item::get($packet->item, $packet->meta, 1);
|
||||
$slot = $this->getCreativeBlock($item);
|
||||
}else{
|
||||
@ -1370,7 +1426,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
|
||||
if($packet->slot === -1){ //Air
|
||||
if(($this->gamemode & 0x01) === Player::CREATIVE){
|
||||
if($this->isCreative()){
|
||||
$found = false;
|
||||
for($i = 0; $i < $this->inventory->getHotbarSize(); ++$i){
|
||||
if($this->inventory->getHotbarSlotIndex($i) === -1){
|
||||
@ -1390,7 +1446,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}elseif(!isset($item) or $slot === -1 or $item->getID() !== $packet->item or $item->getDamage() !== $packet->meta){ // packet error or not implemented
|
||||
$this->inventory->sendContents($this);
|
||||
break;
|
||||
}elseif(($this->gamemode & 0x01) === Player::CREATIVE){
|
||||
}elseif($this->isCreative()){
|
||||
$item = Item::get(
|
||||
Block::$creative[$slot][0],
|
||||
Block::$creative[$slot][1],
|
||||
@ -1405,7 +1461,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
if($this->inAction === true){
|
||||
$this->inAction = false;
|
||||
//$this->entity->updateMetadata();
|
||||
$this->sendMetadata($this->getViewers());
|
||||
}
|
||||
break;
|
||||
case ProtocolInfo::USE_ITEM_PACKET:
|
||||
@ -1440,12 +1496,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
if($packet->face >= 0 and $packet->face <= 5){ //Use Block, place
|
||||
if($this->inAction === true){
|
||||
$this->inAction = false;
|
||||
//$this->entity->updateMetadata();
|
||||
$this->sendMetadata($this->getViewers());
|
||||
}
|
||||
|
||||
if($blockVector->distance($this) > 10){
|
||||
|
||||
}elseif(($this->gamemode & 0x01) === 1){
|
||||
}elseif($this->isCreative()){
|
||||
$item = $this->inventory->getItemInHand();
|
||||
if($this->getLevel()->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){
|
||||
break;
|
||||
@ -1484,7 +1540,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
//TODO: add event
|
||||
$this->inAction = true;
|
||||
$this->startAction = microtime(true);
|
||||
//$this->updateMetadata();
|
||||
$this->sendMetadata($this->getViewers());
|
||||
}
|
||||
break;
|
||||
case ProtocolInfo::PLAYER_ACTION_PACKET:
|
||||
@ -1499,11 +1555,19 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
case 5: //Shot arrow
|
||||
//if($this->entity->inAction === true){
|
||||
if($this->inventory->getItemInHand()->getID() === Item::BOW){
|
||||
$f = 1 * 2 * 1.5;
|
||||
$bow = $this->inventory->getItemInHand();
|
||||
if($this->isSurvival()){
|
||||
if(!$this->inventory->contains(Item::get(Item::ARROW, 0, 1))){
|
||||
$this->inventory->sendContents($this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$f = 1.5;
|
||||
$nbt = new Compound("", [
|
||||
"Pos" => new Enum("Pos", [
|
||||
new Double("", $this->x),
|
||||
new Double("", $this->y + 1.62),
|
||||
new Double("", $this->y + $this->getEyeHeight()),
|
||||
new Double("", $this->z)
|
||||
]),
|
||||
"Motion" => new Enum("Motion", [
|
||||
@ -1516,13 +1580,30 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
new Float("", $this->pitch)
|
||||
]),
|
||||
]);
|
||||
$arrow = new Arrow($this->chunk, $nbt);
|
||||
$arrow->spawnToAll();
|
||||
$arrow = new Arrow($this->chunk, $nbt, $this);
|
||||
|
||||
$ev = new EntityShootBowEvent($this, $bow, $arrow, $f);
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
|
||||
if($ev->isCancelled()){
|
||||
$arrow->kill();
|
||||
}else{
|
||||
if($this->isSurvival()){
|
||||
$this->inventory->removeItem(Item::get(Item::ARROW, 0, 1));
|
||||
$bow->setDamage($bow->getDamage() + 1);
|
||||
$this->inventory->setItemInHand($bow);
|
||||
if($bow->getDamage() >= 385){
|
||||
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 0));
|
||||
}
|
||||
}
|
||||
$arrow->spawnToAll();
|
||||
}
|
||||
}
|
||||
//}
|
||||
$this->startAction = false;
|
||||
//$this->entity->inAction = false;
|
||||
//$this->entity->updateMetadata();
|
||||
$this->inAction = false;
|
||||
$this->sendMetadata($this->getViewers());
|
||||
break;
|
||||
case 6: //get out of the bed
|
||||
$this->stopSleep();
|
||||
@ -1538,14 +1619,14 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$vector = new Vector3($packet->x, $packet->y, $packet->z);
|
||||
|
||||
|
||||
if(($this->gamemode & 0x01) === 1){
|
||||
if($this->isCreative()){
|
||||
$item = $this->inventory->getItemInHand();
|
||||
}else{
|
||||
$item = clone $this->inventory->getItemInHand();
|
||||
}
|
||||
|
||||
if($this->getLevel()->useBreakOn($vector, $item, $this) === true){
|
||||
if(($this->gamemode & 0x01) === 0){
|
||||
if($this->isSurvival()){
|
||||
$this->inventory->setItemInHand($item);
|
||||
$this->inventory->sendHeldItem($this->hasSpawned);
|
||||
}
|
||||
@ -1600,7 +1681,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
if($this->inAction === true){
|
||||
$this->inAction = false;
|
||||
//$this->entity->updateMetadata();
|
||||
$this->sendMetadata($this->getViewers());
|
||||
}
|
||||
break;
|
||||
case ProtocolInfo::INTERACT_PACKET:
|
||||
@ -1623,6 +1704,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
|
||||
if($target instanceof Entity and $this->getGamemode() !== Player::VIEW and $this->blocked === false 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");
|
||||
return;
|
||||
}
|
||||
|
||||
$item = $this->inventory->getItemInHand();
|
||||
$damageTable = [
|
||||
Item::WOODEN_SWORD => 4,
|
||||
@ -1701,7 +1788,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
if($ev->isCancelled()){
|
||||
if($item->isTool() and ($this->gamemode & 0x01) === 0){
|
||||
if($item->isTool() and $this->isSurvival()){
|
||||
$this->inventory->sendContents($this);
|
||||
}
|
||||
break;
|
||||
@ -1709,7 +1796,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
$target->attack($ev->getFinalDamage(), $ev);
|
||||
|
||||
if($item->isTool() and ($this->gamemode & 0x01) === 0){
|
||||
if($item->isTool() and $this->isSurvival()){
|
||||
if($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()){
|
||||
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
|
||||
}
|
||||
@ -1743,12 +1830,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerRespawnEvent($this, $this->getSpawn()));
|
||||
|
||||
$this->teleport($ev->getRespawnPosition());
|
||||
//$this->entity->fire = 0;
|
||||
//$this->entity->air = 300;
|
||||
$this->fireTicks = 0;
|
||||
$this->airTicks = 300;
|
||||
|
||||
$this->setHealth(20);
|
||||
$this->dead = false;
|
||||
//$this->entity->updateMetadata();
|
||||
$this->sendMetadata($this->getViewers());
|
||||
|
||||
$this->sendSettings();
|
||||
$this->inventory->sendContents($this);
|
||||
@ -1768,11 +1855,11 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
if($this->inAction === true){
|
||||
$this->inAction = false;
|
||||
//$this->updateMetadata();
|
||||
$this->sendMetadata($this->getViewers());
|
||||
}
|
||||
switch($packet->event){
|
||||
case 9: //Eating
|
||||
$items = array(
|
||||
$items = [
|
||||
Item::APPLE => 4,
|
||||
Item::MUSHROOM_STEW => 10,
|
||||
Item::BEETROOT_SOUP => 10,
|
||||
@ -1792,7 +1879,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
//Item::COOKIE => 2,
|
||||
//Item::COOKED_FISH => 5,
|
||||
//Item::RAW_FISH => 2,
|
||||
);
|
||||
];
|
||||
$slot = $this->inventory->getItemInHand();
|
||||
if($this->getHealth() < 20 and isset($items[$slot->getID()])){
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerItemConsumeEvent($this, $slot));
|
||||
@ -1832,13 +1919,13 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
|
||||
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
|
||||
$motion = $this->getDirectionVector()->multiply(10);
|
||||
$motion = $this->getDirectionVector()->multiply(0.4);
|
||||
|
||||
$this->getLevel()->dropItem($this->add(0, 1, 0), $item, $motion);
|
||||
$this->getLevel()->dropItem($this->add(0, 1.3, 0), $item, $motion, 40);
|
||||
|
||||
if($this->inAction === true){
|
||||
$this->inAction = false;
|
||||
//$this->updateMetadata();
|
||||
$this->sendMetadata($this->getViewers());
|
||||
}
|
||||
break;
|
||||
case ProtocolInfo::MESSAGE_PACKET:
|
||||
@ -1891,13 +1978,13 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
if($packet->slot > $this->inventory->getSize()){
|
||||
break;
|
||||
}
|
||||
if(($this->gamemode & 0x01) === Player::CREATIVE){
|
||||
if($this->isCreative()){
|
||||
if($this->getCreativeBlock($packet->item) !== -1){
|
||||
$this->inventory->setItem($packet->slot, $packet->item);
|
||||
$this->inventory->setHotbarSlotIndex($packet->slot, $packet->slot); //links $hotbar[$packet->slot] to $slots[$packet->slot]
|
||||
}
|
||||
}else{
|
||||
$this->inventory->setHeldItemSlot($packet->slot);
|
||||
|
||||
}
|
||||
$transaction = new BaseTransaction($this->inventory, $packet->slot, $this->inventory->getItem($packet->slot), $packet->item);
|
||||
}elseif(isset($this->windowIndex[$packet->windowid])){
|
||||
@ -1935,7 +2022,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$inv = $ts->getInventory();
|
||||
if($inv instanceof FurnaceInventory){
|
||||
if($ts->getSlot() === 2){
|
||||
switch($inv->getResult()){
|
||||
switch($inv->getResult()->getID()){
|
||||
case Item::IRON_INGOT:
|
||||
$this->awardAchievement("acquireIron");
|
||||
break;
|
||||
@ -2110,7 +2197,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->tasks = [];
|
||||
|
||||
if($this->connected === true){
|
||||
parent::close();
|
||||
if($this->username != ""){
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerQuitEvent($this, $message));
|
||||
if($this->loggedIn === true){
|
||||
@ -2120,8 +2206,11 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
$this->connected = false;
|
||||
$this->interface->close($this, $reason);
|
||||
$this->server->removePlayer($this);
|
||||
$this->getLevel()->freeAllChunks($this);
|
||||
|
||||
|
||||
parent::close();
|
||||
|
||||
$this->loggedIn = false;
|
||||
|
||||
if(isset($ev) and $this->username != "" and $this->spawned !== false and $ev->getQuitMessage() != ""){
|
||||
@ -2136,30 +2225,38 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->loadQueue = [];
|
||||
unset($this->buffer);
|
||||
}
|
||||
|
||||
$this->server->removePlayer($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles player data saving
|
||||
*/
|
||||
public function save(){
|
||||
if($this->closed){
|
||||
throw new \Exception("Tried to save closed player");
|
||||
}
|
||||
|
||||
parent::saveNBT();
|
||||
$this->namedtag["Level"] = $this->getLevel()->getName();
|
||||
if($this->spawnPosition instanceof Position and $this->spawnPosition->getLevel() instanceof Level){
|
||||
$this->namedtag["SpawnLevel"] = $this->spawnPosition->getLevel()->getName();
|
||||
$this->namedtag["SpawnX"] = (int) $this->spawnPosition->x;
|
||||
$this->namedtag["SpawnY"] = (int) $this->spawnPosition->y;
|
||||
$this->namedtag["SpawnZ"] = (int) $this->spawnPosition->z;
|
||||
}
|
||||
if($this->getLevel() instanceof Level){
|
||||
$this->namedtag["Level"] = $this->getLevel()->getName();
|
||||
if($this->spawnPosition instanceof Position and $this->spawnPosition->getLevel() instanceof Level){
|
||||
$this->namedtag["SpawnLevel"] = $this->spawnPosition->getLevel()->getName();
|
||||
$this->namedtag["SpawnX"] = (int) $this->spawnPosition->x;
|
||||
$this->namedtag["SpawnY"] = (int) $this->spawnPosition->y;
|
||||
$this->namedtag["SpawnZ"] = (int) $this->spawnPosition->z;
|
||||
}
|
||||
|
||||
foreach($this->achievements as $achievement => $status){
|
||||
$this->namedtag->Achievements[$achievement] = new Byte($achievement, $status === true ? 1 : 0);
|
||||
}
|
||||
foreach($this->achievements as $achievement => $status){
|
||||
$this->namedtag->Achievements[$achievement] = new Byte($achievement, $status === true ? 1 : 0);
|
||||
}
|
||||
|
||||
$this->namedtag["playerGameType"] = $this->gamemode;
|
||||
$this->namedtag["lastPlayed"] = floor(microtime(true) * 1000);
|
||||
$this->namedtag["playerGameType"] = $this->gamemode;
|
||||
$this->namedtag["lastPlayed"] = floor(microtime(true) * 1000);
|
||||
|
||||
if($this->username != "" and $this->isOnline() and $this->namedtag instanceof Compound){
|
||||
$this->server->saveOfflinePlayerData($this->username, $this->namedtag);
|
||||
if($this->username != "" and $this->isOnline() and $this->namedtag instanceof Compound){
|
||||
$this->server->saveOfflinePlayerData($this->username, $this->namedtag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2204,8 +2301,18 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
$message = $this->getName() . " was killed";
|
||||
break;
|
||||
case EntityDamageEvent::CAUSE_PROJECTILE:
|
||||
if($ev instanceof EntityDamageByEntityEvent){
|
||||
$e = $ev->getDamager();
|
||||
if($e instanceof Living){
|
||||
$message = $this->getName() . " was shot by " . $e->getName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
$message = $this->getName() . " was shot by arrow";
|
||||
break;
|
||||
case EntityDamageEvent::CAUSE_SUICIDE:
|
||||
|
||||
$message = $this->getName() . " died";
|
||||
break;
|
||||
case EntityDamageEvent::CAUSE_VOID:
|
||||
$message = $this->getName() . " fell out of the world";
|
||||
@ -2220,13 +2327,30 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$message = $this->getName() . " hit the ground too hard";
|
||||
break;
|
||||
|
||||
case EntityDamageEvent::CAUSE_CONTACT:
|
||||
case EntityDamageEvent::CAUSE_PROJECTILE:
|
||||
case EntityDamageEvent::CAUSE_SUFFOCATION:
|
||||
case EntityDamageEvent::CAUSE_FIRE:
|
||||
case EntityDamageEvent::CAUSE_FIRE_TICK:
|
||||
$message = $this->getName() . " suffocated in a wall";
|
||||
break;
|
||||
|
||||
case EntityDamageEvent::CAUSE_LAVA:
|
||||
$message = $this->getName() . " tried to swim in lava";
|
||||
break;
|
||||
|
||||
case EntityDamageEvent::CAUSE_FIRE:
|
||||
$message = $this->getName() . " went up in flames";
|
||||
break;
|
||||
|
||||
case EntityDamageEvent::CAUSE_FIRE_TICK:
|
||||
$message = $this->getName() . " burned to death";
|
||||
break;
|
||||
|
||||
case EntityDamageEvent::CAUSE_DROWNING:
|
||||
$message = $this->getName() . " drowned";
|
||||
break;
|
||||
|
||||
case EntityDamageEvent::CAUSE_CONTACT:
|
||||
$message = $this->getName() . " was pricked to death";
|
||||
break;
|
||||
|
||||
case EntityDamageEvent::CAUSE_BLOCK_EXPLOSION:
|
||||
case EntityDamageEvent::CAUSE_ENTITY_EXPLOSION:
|
||||
case EntityDamageEvent::CAUSE_MAGIC:
|
||||
@ -2238,7 +2362,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerDeathEvent($this, $this->getDrops(), $message));
|
||||
|
||||
$this->server->broadcast($ev->getDeathMessage(), Server::BROADCAST_CHANNEL_USERS);
|
||||
if($ev->getDeathMessage() != ""){
|
||||
$this->server->broadcast($ev->getDeathMessage(), Server::BROADCAST_CHANNEL_USERS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2271,11 +2397,37 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->eid = 0;
|
||||
$pk->event = 2;
|
||||
$this->dataPacket($pk);
|
||||
|
||||
parent::attack($damage, $source);
|
||||
|
||||
if($this->getLastDamageCause() === $source){
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->eid = 0;
|
||||
$pk->event = 2;
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
}
|
||||
|
||||
public function getData(){ //TODO
|
||||
$flags = 0;
|
||||
$flags |= $this->fireTicks > 0 ? 1 : 0;
|
||||
//$flags |= ($this->crouched === true ? 0b10:0) << 1;
|
||||
$flags |= ($this->inAction === true ? 0b10000:0);
|
||||
$d = [
|
||||
0 => ["type" => 0, "value" => $flags],
|
||||
1 => ["type" => 1, "value" => $this->airTicks],
|
||||
16 => ["type" => 0, "value" => 0],
|
||||
17 => ["type" => 6, "value" => [0, 0, 0]],
|
||||
];
|
||||
|
||||
|
||||
if($this->sleeping !== false){
|
||||
$d[16]["value"] = 2;
|
||||
$d[17]["value"] = [$this->sleeping->x, $this->sleeping->y, $this->sleeping->z];
|
||||
}
|
||||
|
||||
|
||||
return $d;
|
||||
}
|
||||
|
||||
public function teleport(Vector3 $pos, $yaw = null, $pitch = null){
|
||||
@ -2289,11 +2441,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$pk = new MovePlayerPacket;
|
||||
$pk->eid = 0;
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y + 1.62; //teleport from head
|
||||
$pk->y = $this->y + $this->getEyeHeight();
|
||||
$pk->z = $this->z;
|
||||
$pk->bodyYaw = $this->yaw;
|
||||
$pk->pitch = $this->pitch;
|
||||
$pk->yaw = $this->yaw;
|
||||
$pk->teleport = true;
|
||||
$this->directDataPacket($pk);
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ namespace pocketmine {
|
||||
use raklib\RakLib;
|
||||
|
||||
const VERSION = "Alpha_1.4dev";
|
||||
const API_VERSION = "1.3.0";
|
||||
const API_VERSION = "1.4.0";
|
||||
const CODENAME = "絶好(Zekkou)ケーキ(Cake)";
|
||||
const MINECRAFT_VERSION = "v0.9.5 alpha";
|
||||
|
||||
@ -89,21 +89,17 @@ namespace pocketmine {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(!class_exists("SplClassLoader", false)){
|
||||
require_once(\pocketmine\PATH . "src/spl/SplClassLoader.php");
|
||||
if(!class_exists("ClassLoader", false)){
|
||||
require_once(\pocketmine\PATH . "src/spl/ClassLoader.php");
|
||||
require_once(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
|
||||
require_once(\pocketmine\PATH . "src/pocketmine/CompatibleClassLoader.php");
|
||||
}
|
||||
|
||||
$autoloader = new \SplClassLoader();
|
||||
$autoloader->setMode(\SplAutoloader::MODE_DEBUG);
|
||||
$autoloader->add("pocketmine", [
|
||||
\pocketmine\PATH . "src"
|
||||
]);
|
||||
|
||||
$autoloader = new CompatibleClassLoader();
|
||||
$autoloader->addPath(\pocketmine\PATH . "src");
|
||||
$autoloader->addPath(\pocketmine\PATH . "src" . DIRECTORY_SEPARATOR . "spl");
|
||||
$autoloader->addPath(\pocketmine\PATH . "src" . DIRECTORY_SEPARATOR . "raklib");
|
||||
$autoloader->register(true);
|
||||
if(!class_exists("raklib\\RakLib", false)){
|
||||
require(\pocketmine\PATH . "src/raklib/raklib/RakLib.php");
|
||||
}
|
||||
RakLib::bootstrap($autoloader);
|
||||
|
||||
//Startup code. Do not look at it, it can harm you. Most of them are hacks to fix date-related bugs, or basic functions used after this
|
||||
|
||||
@ -120,10 +116,10 @@ namespace pocketmine {
|
||||
$i = array_map("intval", explode(":", trim($hour[0])));
|
||||
@exec("date.exe /T", $date);
|
||||
$j = array_map("intval", explode(substr($date[0], 2, 1), trim($date[0])));
|
||||
$offset = round((mktime($i[0], $i[1], 0, $j[1], $j[0], $j[2]) - $time) / 60) * 60;
|
||||
$offset = @round((mktime($i[0], $i[1], 0, $j[1], $j[0], $j[2]) - $time) / 60) * 60;
|
||||
}else{
|
||||
@exec("date +%s", $t);
|
||||
$offset = round((intval(trim($t[0])) - time()) / 60) * 60;
|
||||
$offset = @round((intval(trim($t[0])) - time()) / 60) * 60;
|
||||
}
|
||||
|
||||
$daylight = (int) date("I");
|
||||
@ -149,7 +145,7 @@ namespace pocketmine {
|
||||
ini_set("memory_limit", "256M"); //Default
|
||||
define("pocketmine\\START_TIME", microtime(true));
|
||||
|
||||
$opts = getopt("", array("enable-ansi", "disable-ansi", "data:", "plugins:", "no-wizard"));
|
||||
$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);
|
||||
@ -158,6 +154,15 @@ namespace pocketmine {
|
||||
|
||||
$logger = new MainLogger(\pocketmine\DATA . "server.log", \pocketmine\ANSI);
|
||||
|
||||
if(isset($opts["enable-profiler"])){
|
||||
if(function_exists("profiler_enable")){
|
||||
\profiler_enable();
|
||||
$logger->notice("Execution is being profiled");
|
||||
}else{
|
||||
$logger->notice("No profiler found. Please install https://github.com/krakjoe/profiler");
|
||||
}
|
||||
}
|
||||
|
||||
function kill($pid){
|
||||
switch(Utils::getOS()){
|
||||
case "win":
|
||||
@ -209,7 +214,7 @@ namespace pocketmine {
|
||||
if(error_reporting() === 0){ //@ error-control
|
||||
return false;
|
||||
}
|
||||
$errorConversion = array(
|
||||
$errorConversion = [
|
||||
E_ERROR => "E_ERROR",
|
||||
E_WARNING => "E_WARNING",
|
||||
E_PARSE => "E_PARSE",
|
||||
@ -225,7 +230,7 @@ namespace pocketmine {
|
||||
E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
|
||||
E_DEPRECATED => "E_DEPRECATED",
|
||||
E_USER_DEPRECATED => "E_USER_DEPRECATED",
|
||||
);
|
||||
];
|
||||
$type = ($errno === E_ERROR or $errno === E_WARNING or $errno === E_USER_ERROR or $errno === E_USER_WARNING) ? LogLevel::ERROR : LogLevel::NOTICE;
|
||||
$errno = isset($errorConversion[$errno]) ? $errorConversion[$errno] : $errno;
|
||||
if(($pos = strpos($errstr, "\n")) !== false){
|
||||
@ -255,8 +260,8 @@ namespace pocketmine {
|
||||
|
||||
$errors = 0;
|
||||
|
||||
if(version_compare("5.4.0", PHP_VERSION) > 0){
|
||||
$logger->critical("Use PHP >= 5.4.0");
|
||||
if(version_compare("5.6.0", PHP_VERSION) > 0){
|
||||
$logger->critical("You must use PHP >= 5.6");
|
||||
++$errors;
|
||||
}
|
||||
|
||||
@ -274,8 +279,8 @@ namespace pocketmine {
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "2.0.4") < 0){
|
||||
$logger->critical("pthreads >= 2.0.4 is required, while you have $pthreads_version.");
|
||||
if(version_compare($pthreads_version, "2.0.8") < 0){
|
||||
$logger->critical("pthreads >= 2.0.8 is required, while you have $pthreads_version.");
|
||||
++$errors;
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,6 @@ use pocketmine\nbt\tag\Short;
|
||||
use pocketmine\nbt\tag\String;
|
||||
use pocketmine\network\protocol\DataPacket;
|
||||
use pocketmine\network\query\QueryHandler;
|
||||
use pocketmine\network\query\QueryPacket;
|
||||
use pocketmine\network\RakLibInterface;
|
||||
use pocketmine\network\rcon\RCON;
|
||||
use pocketmine\network\SourceInterface;
|
||||
@ -128,9 +127,8 @@ class Server{
|
||||
*/
|
||||
private $tickCounter;
|
||||
private $nextTick = 0;
|
||||
private $tickMeasure = 20;
|
||||
private $tickTime = 0;
|
||||
private $inTick = false;
|
||||
private $tickAverage = [20,20,20,20,20];
|
||||
private $useAverage = [20,20,20,20,20];
|
||||
|
||||
/** @var \AttachableThreadedLogger */
|
||||
private $logger;
|
||||
@ -455,7 +453,7 @@ class Server{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \SplClassLoader
|
||||
* @return \ClassLoader
|
||||
*/
|
||||
public function getLoader(){
|
||||
return $this->autoloader;
|
||||
@ -537,7 +535,16 @@ class Server{
|
||||
* @return float
|
||||
*/
|
||||
public function getTicksPerSecond(){
|
||||
return round((0.05 / $this->tickMeasure) * 20, 2);
|
||||
return round(array_sum($this->tickAverage) / count($this->tickAverage), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TPS usage/load in %
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getTickUsage(){
|
||||
return round((array_sum($this->useAverage) / count($this->useAverage)) * 100, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -626,14 +633,14 @@ class Server{
|
||||
$path = $this->getDataPath() . "players/";
|
||||
if(!file_exists($path . "$name.dat")){
|
||||
$spawn = $this->getDefaultLevel()->getSafeSpawn();
|
||||
$nbt = new Compound(false, array(
|
||||
$nbt = new Compound(false, [
|
||||
new Long("firstPlayed", floor(microtime(true) * 1000)),
|
||||
new Long("lastPlayed", floor(microtime(true) * 1000)),
|
||||
new Enum("Pos", array(
|
||||
new Enum("Pos", [
|
||||
new Double(0, $spawn->x),
|
||||
new Double(1, $spawn->y),
|
||||
new Double(2, $spawn->z)
|
||||
)),
|
||||
]),
|
||||
new String("Level", $this->getDefaultLevel()->getName()),
|
||||
//new String("SpawnLevel", $this->getDefaultLevel()->getName()),
|
||||
//new Int("SpawnX", (int) $spawn->x),
|
||||
@ -643,22 +650,22 @@ class Server{
|
||||
new Enum("Inventory", []),
|
||||
new Compound("Achievements", []),
|
||||
new Int("playerGameType", $this->getGamemode()),
|
||||
new Enum("Motion", array(
|
||||
new Enum("Motion", [
|
||||
new Double(0, 0.0),
|
||||
new Double(1, 0.0),
|
||||
new Double(2, 0.0)
|
||||
)),
|
||||
new Enum("Rotation", array(
|
||||
]),
|
||||
new Enum("Rotation", [
|
||||
new Float(0, 0.0),
|
||||
new Float(1, 0.0)
|
||||
)),
|
||||
]),
|
||||
new Float("FallDistance", 0.0),
|
||||
new Short("Fire", 0),
|
||||
new Short("Air", 0),
|
||||
new Byte("OnGround", 1),
|
||||
new Byte("Invulnerable", 0),
|
||||
new String("NameTag", $name),
|
||||
));
|
||||
]);
|
||||
$nbt->Pos->setTagType(NBT::TAG_Double);
|
||||
$nbt->Inventory->setTagType(NBT::TAG_Compound);
|
||||
$nbt->Motion->setTagType(NBT::TAG_Double);
|
||||
@ -678,35 +685,35 @@ class Server{
|
||||
$this->logger->notice("Old Player data found for \"" . $name . "\", upgrading profile");
|
||||
foreach($data->get("inventory") as $slot => $item){
|
||||
if(count($item) === 3){
|
||||
$nbt->Inventory[$slot + 9] = new Compound(false, array(
|
||||
$nbt->Inventory[$slot + 9] = new Compound(false, [
|
||||
new Short("id", $item[0]),
|
||||
new Short("Damage", $item[1]),
|
||||
new Byte("Count", $item[2]),
|
||||
new Byte("Slot", $slot + 9),
|
||||
new Byte("TrueSlot", $slot + 9)
|
||||
));
|
||||
]);
|
||||
}
|
||||
}
|
||||
foreach($data->get("hotbar") as $slot => $itemSlot){
|
||||
if(isset($nbt->Inventory[$itemSlot + 9])){
|
||||
$item = $nbt->Inventory[$itemSlot + 9];
|
||||
$nbt->Inventory[$slot] = new Compound(false, array(
|
||||
$nbt->Inventory[$slot] = new Compound(false, [
|
||||
new Short("id", $item["id"]),
|
||||
new Short("Damage", $item["Damage"]),
|
||||
new Byte("Count", $item["Count"]),
|
||||
new Byte("Slot", $slot),
|
||||
new Byte("TrueSlot", $item["TrueSlot"])
|
||||
));
|
||||
]);
|
||||
}
|
||||
}
|
||||
foreach($data->get("armor") as $slot => $item){
|
||||
if(count($item) === 2){
|
||||
$nbt->Inventory[$slot + 100] = new Compound(false, array(
|
||||
$nbt->Inventory[$slot + 100] = new Compound(false, [
|
||||
new Short("id", $item[0]),
|
||||
new Short("Damage", $item[1]),
|
||||
new Byte("Count", 1),
|
||||
new Byte("Slot", $slot + 100)
|
||||
));
|
||||
]);
|
||||
}
|
||||
}
|
||||
foreach($data->get("achievements") as $achievement => $status){
|
||||
@ -788,7 +795,7 @@ class Server{
|
||||
$matchedPlayers = [];
|
||||
foreach($this->getOnlinePlayers() as $player){
|
||||
if(strtolower($player->getName()) === $partialName){
|
||||
$matchedPlayers = array($player);
|
||||
$matchedPlayers = [$player];
|
||||
break;
|
||||
}elseif(stripos($player->getName(), $partialName) !== false){
|
||||
$matchedPlayers[] = $player;
|
||||
@ -802,7 +809,12 @@ class Server{
|
||||
* @param Player $player
|
||||
*/
|
||||
public function removePlayer(Player $player){
|
||||
unset($this->players[$player->getAddress() . ":" . $player->getPort()]);
|
||||
foreach($this->players as $identifier => $p){
|
||||
if($player === $p){
|
||||
unset($this->players[$identifier]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1048,12 +1060,8 @@ class Server{
|
||||
if($generator !== null and class_exists($generator) and is_subclass_of($generator, "pocketmine\\level\\generator\\Generator")){
|
||||
$generator = new $generator($options);
|
||||
}else{
|
||||
if(strtoupper($this->getLevelType()) == "FLAT"){
|
||||
$generator = Generator::getGenerator("flat");
|
||||
$options["preset"] = $this->getConfigString("generator-settings", "");
|
||||
}else{
|
||||
$generator = Generator::getGenerator("normal");
|
||||
}
|
||||
$options["preset"] = $this->getConfigString("generator-settings", "");
|
||||
$generator = Generator::getGenerator($this->getLevelType());
|
||||
}
|
||||
|
||||
if(($provider = LevelProviderManager::getProviderByName($providerName = $this->getProperty("level-settings.default-format", "mcregion"))) === null){
|
||||
@ -1142,7 +1150,7 @@ class Server{
|
||||
* @return string
|
||||
*/
|
||||
public function getConfigString($variable, $defaultValue = ""){
|
||||
$v = getopt("", array("$variable::"));
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
return (string) $v[$variable];
|
||||
}
|
||||
@ -1192,7 +1200,7 @@ class Server{
|
||||
* @return int
|
||||
*/
|
||||
public function getConfigInt($variable, $defaultValue = 0){
|
||||
$v = getopt("", array("$variable::"));
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
return (int) $v[$variable];
|
||||
}
|
||||
@ -1215,7 +1223,7 @@ class Server{
|
||||
* @return boolean
|
||||
*/
|
||||
public function getConfigBoolean($variable, $defaultValue = false){
|
||||
$v = getopt("", array("$variable::"));
|
||||
$v = getopt("", ["$variable::"]);
|
||||
if(isset($v[$variable])){
|
||||
$value = $v[$variable];
|
||||
}else{
|
||||
@ -1377,13 +1385,13 @@ class Server{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \SplClassLoader $autoloader
|
||||
* @param \ClassLoader $autoloader
|
||||
* @param \ThreadedLogger $logger
|
||||
* @param string $filePath
|
||||
* @param string $dataPath
|
||||
* @param string $pluginPath
|
||||
*/
|
||||
public function __construct(\SplClassLoader $autoloader, \ThreadedLogger $logger, $filePath, $dataPath, $pluginPath){
|
||||
public function __construct(\ClassLoader $autoloader, \ThreadedLogger $logger, $filePath, $dataPath, $pluginPath){
|
||||
self::$instance = $this;
|
||||
|
||||
$this->autoloader = $autoloader;
|
||||
@ -1427,7 +1435,7 @@ class Server{
|
||||
$this->config = new Config($this->dataPath . "pocketmine.yml", Config::YAML, []);
|
||||
|
||||
$this->logger->info("Loading server properties...");
|
||||
$this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, array(
|
||||
$this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, [
|
||||
"motd" => "Minecraft: PE Server",
|
||||
"server-port" => 19132,
|
||||
"memory-limit" => "256M",
|
||||
@ -1451,7 +1459,7 @@ class Server{
|
||||
"enable-rcon" => false,
|
||||
"rcon.password" => substr(base64_encode(Utils::getRandomBytes(20, false)), 3, 10),
|
||||
"auto-save" => true,
|
||||
));
|
||||
]);
|
||||
|
||||
ServerScheduler::$WORKERS = $this->getProperty("settings.async-workers", ServerScheduler::$WORKERS);
|
||||
|
||||
@ -1463,15 +1471,15 @@ class Server{
|
||||
|
||||
$this->maxPlayers = $this->getConfigInt("max-players", 20);
|
||||
|
||||
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "128M")))) !== false){
|
||||
$value = array("M" => 1, "G" => 1024);
|
||||
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "256M")))) !== false){
|
||||
$value = ["M" => 1, "G" => 1024];
|
||||
$real = ((int) substr($memory, 0, -1)) * $value[substr($memory, -1)];
|
||||
if($real < 128){
|
||||
$this->logger->warning("PocketMine-MP may not work right with less than 128MB of RAM", true, true, 0);
|
||||
$this->logger->warning($this->getName() . " may not work right with less than 128MB of RAM", true, true, 0);
|
||||
}
|
||||
@ini_set("memory_limit", $memory);
|
||||
}else{
|
||||
$this->setConfigString("memory-limit", "128M");
|
||||
$this->setConfigString("memory-limit", "256M");
|
||||
}
|
||||
|
||||
if($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3){
|
||||
@ -1489,8 +1497,8 @@ class Server{
|
||||
|
||||
Level::$COMPRESSION_LEVEL = $this->getProperty("chunk-sending.compression-level", 7);
|
||||
|
||||
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0 and function_exists("cli_set_process_title")){
|
||||
@cli_set_process_title("PocketMine-MP " . $this->getPocketMineVersion());
|
||||
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0){
|
||||
@cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion());
|
||||
}
|
||||
|
||||
$this->logger->info("Starting Minecraft PE server on " . ($this->getIp() === "" ? "*" : $this->getIp()) . ":" . $this->getPort());
|
||||
@ -1499,8 +1507,11 @@ class Server{
|
||||
|
||||
$this->addInterface($this->mainInterface = new RakLibInterface($this));
|
||||
|
||||
$this->logger->info("This server is running PocketMine-MP version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(false) . TextFormat::RESET . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0);
|
||||
$this->logger->info("PocketMine-MP is distributed under the LGPL License", true, true, 0);
|
||||
$this->logger->info("This server is running " . $this->getName() . " version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(false) . TextFormat::RESET . " \"" . $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");
|
||||
Timings::init();
|
||||
|
||||
$this->consoleSender = new ConsoleCommandSender();
|
||||
$this->commandMap = new SimpleCommandMap($this);
|
||||
@ -1510,9 +1521,6 @@ class Server{
|
||||
Item::init();
|
||||
$this->craftingManager = new CraftingManager();
|
||||
|
||||
PluginManager::$pluginParentTimer = new TimingsHandler("** Plugins");
|
||||
Timings::init();
|
||||
|
||||
$this->pluginManager = new PluginManager($this, $this->commandMap);
|
||||
$this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender);
|
||||
$this->pluginManager->setUseTimings($this->getProperty("settings.enable-profiling", false));
|
||||
@ -1538,6 +1546,13 @@ class Server{
|
||||
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "normal");
|
||||
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "default");
|
||||
|
||||
//Temporal workaround, pthreads static property nullification test
|
||||
if(PluginManager::$pluginParentTimer === null){
|
||||
$this->getLogger()->emergency("You are using an invalid pthreads version. Please update your binaries.");
|
||||
kill(getmypid());
|
||||
return;
|
||||
}
|
||||
|
||||
foreach($this->getProperty("worlds", []) as $name => $worldSetting){
|
||||
if($this->loadLevel($name) === false){
|
||||
$seed = $this->getProperty("worlds.$name.seed", time());
|
||||
@ -1558,7 +1573,7 @@ class Server{
|
||||
if($this->getDefaultLevel() === null){
|
||||
$default = $this->getConfigString("level-name", "world");
|
||||
if(trim($default) == ""){
|
||||
trigger_error("level-name cannot be null, using default", E_USER_WARNING);
|
||||
$this->getLogger()->warning("level-name cannot be null, using default");
|
||||
$default = "world";
|
||||
$this->setConfigString("level-name", "world");
|
||||
}
|
||||
@ -1582,7 +1597,7 @@ class Server{
|
||||
|
||||
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask("pocketmine\\utils\\Cache::cleanup"), $this->getProperty("ticks-per.cache-cleanup", 900), $this->getProperty("ticks-per.cache-cleanup", 900));
|
||||
if($this->getConfigBoolean("auto-save", true) === true and $this->getProperty("ticks-per.autosave", 6000) > 0){
|
||||
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "doAutoSave")), $this->getProperty("ticks-per.autosave", 6000), $this->getProperty("ticks-per.autosave", 6000));
|
||||
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([$this, "doAutoSave"]), $this->getProperty("ticks-per.autosave", 6000), $this->getProperty("ticks-per.autosave", 6000));
|
||||
}
|
||||
|
||||
if($this->getProperty("chunk-gc.period-in-ticks", 600) > 0){
|
||||
@ -1646,7 +1661,7 @@ class Server{
|
||||
public function enablePlugins($type){
|
||||
foreach($this->pluginManager->getPlugins() as $plugin){
|
||||
if(!$plugin->isEnabled() and $plugin->getDescription()->getOrder() === $type){
|
||||
$this->loadPlugin($plugin);
|
||||
$this->enablePlugin($plugin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1659,10 +1674,19 @@ class Server{
|
||||
/**
|
||||
* @param Plugin $plugin
|
||||
*/
|
||||
public function loadPlugin(Plugin $plugin){
|
||||
public function enablePlugin(Plugin $plugin){
|
||||
$this->pluginManager->enablePlugin($plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Plugin $plugin
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function loadPlugin(Plugin $plugin){
|
||||
$this->enablePlugin($plugin);
|
||||
}
|
||||
|
||||
public function disablePlugins(){
|
||||
$this->pluginManager->disablePlugins();
|
||||
}
|
||||
@ -1716,14 +1740,14 @@ class Server{
|
||||
$this->maxPlayers = $this->getConfigInt("max-players", 20);
|
||||
|
||||
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "256M")))) !== false){
|
||||
$value = array("M" => 1, "G" => 1024);
|
||||
$value = ["M" => 1, "G" => 1024];
|
||||
$real = ((int) substr($memory, 0, -1)) * $value[substr($memory, -1)];
|
||||
if($real < 256){
|
||||
$this->logger->warning("PocketMine-MP may not work right with less than 256MB of RAM", true, true, 0);
|
||||
$this->logger->warning($this->getName() . " may not work right with less than 256MB of RAM", true, true, 0);
|
||||
}
|
||||
@ini_set("memory_limit", $memory);
|
||||
}else{
|
||||
$this->setConfigString("memory-limit", "128M");
|
||||
$this->setConfigString("memory-limit", "256M");
|
||||
}
|
||||
|
||||
if($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3){
|
||||
@ -1800,7 +1824,7 @@ class Server{
|
||||
|
||||
|
||||
if($this->getProperty("settings.send-usage", true) !== false){
|
||||
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "sendUsage")), 6000, 6000);
|
||||
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([$this, "sendUsage"]), 6000, 6000);
|
||||
$this->sendUsage();
|
||||
}
|
||||
|
||||
@ -1813,12 +1837,16 @@ class Server{
|
||||
$this->tickCounter = 0;
|
||||
|
||||
if(function_exists("pcntl_signal")){
|
||||
pcntl_signal(SIGTERM, array($this, "shutdown"));
|
||||
pcntl_signal(SIGINT, array($this, "shutdown"));
|
||||
pcntl_signal(SIGHUP, array($this, "shutdown"));
|
||||
pcntl_signal(SIGTERM, [$this, "handleSignal"]);
|
||||
pcntl_signal(SIGINT, [$this, "handleSignal"]);
|
||||
pcntl_signal(SIGHUP, [$this, "handleSignal"]);
|
||||
$this->getScheduler()->scheduleRepeatingTask(new CallbackTask("pcntl_signal_dispatch"), 5);
|
||||
}
|
||||
|
||||
$this->logger->info("Default game type: " . self::getGamemodeString($this->getGamemode())); //TODO: string name
|
||||
|
||||
$this->getScheduler()->scheduleRepeatingTask(new CallbackTask([$this, "checkTicks"]), 20 * 5);
|
||||
|
||||
$this->logger->info("Default game type: " . self::getGamemodeString($this->getGamemode()));
|
||||
|
||||
$this->logger->info("Done (" . round(microtime(true) - \pocketmine\START_TIME, 3) . 's)! For help, type "help" or "?"');
|
||||
|
||||
@ -1828,6 +1856,12 @@ class Server{
|
||||
gc_collect_cycles();
|
||||
}
|
||||
|
||||
public function handleSignal($signo){
|
||||
if($signo === SIGTERM or $signo === SIGINT or $signo === SIGHUP){
|
||||
$this->shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public function checkTicks(){
|
||||
if($this->getTicksPerSecond() < 12){
|
||||
$this->logger->warning("Can't keep up! Is the server overloaded?");
|
||||
@ -1878,13 +1912,14 @@ class Server{
|
||||
}
|
||||
}elseif(\Phar::running(true) == ""){
|
||||
return;
|
||||
}elseif($dump->getData()["type"] === "E_PARSE" or $dump->getData()["type"] === "E_COMPILE_ERROR"){
|
||||
}
|
||||
if($dump->getData()["type"] === "E_PARSE" or $dump->getData()["type"] === "E_COMPILE_ERROR"){
|
||||
return;
|
||||
}
|
||||
|
||||
$reply = Utils::postURL("http://" . $this->getProperty("auto-report.host", "crash.pocketmine.net") . "/submit/api", [
|
||||
"report" => "yes",
|
||||
"name" => "PocketMine-MP " . $this->getPocketMineVersion(),
|
||||
"name" => $this->getName() . " " . $this->getPocketMineVersion(),
|
||||
"email" => "crash@pocketmine.net",
|
||||
"reportPaste" => base64_encode($dump->getEncodedData())
|
||||
]);
|
||||
@ -1901,31 +1936,15 @@ class Server{
|
||||
|
||||
}
|
||||
|
||||
public function __debugInfo(){
|
||||
return get_class($this);
|
||||
}
|
||||
|
||||
private function tickProcessor(){
|
||||
$lastLoop = 0;
|
||||
$connectionTimer = Timings::$connectionTimer;
|
||||
while($this->isRunning){
|
||||
$connectionTimer->startTiming();
|
||||
foreach($this->interfaces as $interface){
|
||||
if($interface->process()){
|
||||
$lastLoop = 0;
|
||||
}
|
||||
}
|
||||
$connectionTimer->stopTiming();
|
||||
|
||||
$this->generationManager->handlePackets();
|
||||
|
||||
++$lastLoop;
|
||||
|
||||
if(($ticks = $this->tick()) !== true){
|
||||
if($lastLoop > 2 and $lastLoop < 16){
|
||||
usleep(1000);
|
||||
}elseif($lastLoop < 128){
|
||||
usleep(2000);
|
||||
}else{
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
$this->tick();
|
||||
usleep((int) max(1, ($this->nextTick - microtime(true)) * 1000000));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1935,32 +1954,6 @@ class Server{
|
||||
|
||||
private function checkTickUpdates($currentTick){
|
||||
|
||||
//TODO: move this to each Level
|
||||
|
||||
//Update entities that need update
|
||||
if(count(Entity::$needUpdate) > 0){
|
||||
Timings::$tickEntityTimer->startTiming();
|
||||
foreach(Entity::$needUpdate as $id => $entity){
|
||||
if($entity->onUpdate() === false){
|
||||
unset(Entity::$needUpdate[$id]);
|
||||
}
|
||||
}
|
||||
Timings::$tickEntityTimer->stopTiming();
|
||||
}
|
||||
|
||||
//Update tiles that need update
|
||||
if(count(Tile::$needUpdate) > 0){
|
||||
Timings::$tickTileEntityTimer->startTiming();
|
||||
foreach(Tile::$needUpdate as $id => $tile){
|
||||
if($tile->onUpdate() === false){
|
||||
unset(Tile::$needUpdate[$id]);
|
||||
}
|
||||
}
|
||||
Timings::$tickTileEntityTimer->stopTiming();
|
||||
}
|
||||
|
||||
//TODO: Add level blocks
|
||||
|
||||
//Do level ticks
|
||||
foreach($this->getLevels() as $level){
|
||||
$level->doTick($currentTick);
|
||||
@ -1968,10 +1961,13 @@ class Server{
|
||||
}
|
||||
|
||||
public function doAutoSave(){
|
||||
|
||||
Timings::$worldSaveTimer->startTiming();
|
||||
foreach($this->getOnlinePlayers() as $player){
|
||||
$player->save();
|
||||
foreach($this->getOnlinePlayers() as $index => $player){
|
||||
if($player->isOnline()){
|
||||
$player->save();
|
||||
}elseif(!$player->isConnected()){
|
||||
unset($this->players[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->getLevels() as $level){
|
||||
@ -1992,14 +1988,15 @@ class Server{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$plist = "";
|
||||
foreach($this->getPluginManager()->getPlugins() as $p){
|
||||
$d = $p->getDescription();
|
||||
$plist .= str_replace(array(";", ":"), "", $d->getName()) . ":" . str_replace(array(";", ":"), "", $d->getVersion()) . ";";
|
||||
$plist .= str_replace([";", ":"], "", $d->getName()) . ":" . str_replace([";", ":"], "", $d->getVersion()) . ";";
|
||||
}
|
||||
|
||||
$version = new VersionString();
|
||||
$this->lastSendUsage = new SendUsageTask("http://stats.pocketmine.net/usage.php", array(
|
||||
$this->lastSendUsage = new SendUsageTask("http://stats.pocketmine.net/usage.php", [
|
||||
"serverid" => Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() . ":" . $this->getPort()), 0, 8)),
|
||||
"port" => $this->getPort(),
|
||||
"os" => Utils::getOS(),
|
||||
@ -2013,14 +2010,14 @@ class Server{
|
||||
"online" => count($this->players),
|
||||
"max" => $this->getMaxPlayers(),
|
||||
"plugins" => $plist,
|
||||
));
|
||||
]);
|
||||
|
||||
$this->scheduler->scheduleAsyncTask($this->lastSendUsage);
|
||||
}
|
||||
|
||||
private function titleTick(){
|
||||
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0 and \pocketmine\ANSI === true){
|
||||
echo "\x1b]0;PocketMine-MP " . $this->getPocketMineVersion() . " | Online " . count($this->players) . "/" . $this->getMaxPlayers() . " | RAM " . round((memory_get_usage() / 1024) / 1024, 2) . "/" . round((memory_get_usage(true) / 1024) / 1024, 2) . " MB | U " . round($this->mainInterface->getUploadUsage() / 1024, 2) . " D " . round($this->mainInterface->getDownloadUsage() / 1024, 2) . " kB/s | TPS " . $this->getTicksPerSecond() . "\x07";
|
||||
echo "\x1b]0;". $this->getName() . " " . $this->getPocketMineVersion() . " | Online " . count($this->players) . "/" . $this->getMaxPlayers() . " | RAM " . round((memory_get_usage() / 1024) / 1024, 2) . "/" . round((memory_get_usage(true) / 1024) / 1024, 2) . " MB | U " . round($this->mainInterface->getUploadUsage() / 1024, 2) . " D " . round($this->mainInterface->getDownloadUsage() / 1024, 2) . " kB/s | TPS " . $this->getTicksPerSecond() . " | Load ". $this->getTickUsage() . "%\x07";
|
||||
}
|
||||
}
|
||||
|
||||
@ -2028,44 +2025,56 @@ class Server{
|
||||
/**
|
||||
* Tries to execute a server tick
|
||||
*/
|
||||
public function tick(){
|
||||
if($this->inTick === false){
|
||||
$tickTime = microtime(true);
|
||||
if($tickTime < $this->nextTick){
|
||||
return false;
|
||||
}
|
||||
|
||||
Timings::$serverTickTimer->startTiming();
|
||||
|
||||
$this->inTick = true; //Fix race conditions
|
||||
++$this->tickCounter;
|
||||
|
||||
$this->checkConsole();
|
||||
Timings::$schedulerTimer->startTiming();
|
||||
$this->scheduler->mainThreadHeartbeat($this->tickCounter);
|
||||
Timings::$schedulerTimer->stopTiming();
|
||||
$this->checkTickUpdates($this->tickCounter);
|
||||
|
||||
if(($this->tickCounter & 0b1111) === 0){
|
||||
$this->titleTick();
|
||||
if(isset($this->queryHandler) and ($this->tickCounter & 0b111111111) === 0){
|
||||
$this->queryHandler->regenerateInfo();
|
||||
}
|
||||
}
|
||||
|
||||
TimingsHandler::tick();
|
||||
|
||||
$this->tickMeasure = (($time = microtime(true)) - $this->tickTime);
|
||||
$this->tickTime = $time;
|
||||
$this->nextTick = 0.05 * (0.05 / max(0.05, $this->tickMeasure)) + $time;
|
||||
$this->inTick = false;
|
||||
|
||||
Timings::$serverTickTimer->stopTiming();
|
||||
|
||||
return true;
|
||||
private function tick(){
|
||||
$tickTime = microtime(true);
|
||||
if($tickTime < $this->nextTick){
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
Timings::$serverTickTimer->startTiming();
|
||||
|
||||
++$this->tickCounter;
|
||||
|
||||
$this->checkConsole();
|
||||
|
||||
Timings::$connectionTimer->startTiming();
|
||||
foreach($this->interfaces as $interface){
|
||||
$interface->process();
|
||||
}
|
||||
Timings::$connectionTimer->stopTiming();
|
||||
|
||||
Timings::$schedulerTimer->startTiming();
|
||||
$this->scheduler->mainThreadHeartbeat($this->tickCounter);
|
||||
Timings::$schedulerTimer->stopTiming();
|
||||
|
||||
$this->checkTickUpdates($this->tickCounter);
|
||||
|
||||
if(($this->tickCounter & 0b1111) === 0){
|
||||
$this->titleTick();
|
||||
if(isset($this->queryHandler) and ($this->tickCounter & 0b111111111) === 0){
|
||||
$this->queryHandler->regenerateInfo();
|
||||
}
|
||||
}
|
||||
|
||||
$this->generationManager->handlePackets();
|
||||
|
||||
Timings::$serverTickTimer->stopTiming();
|
||||
|
||||
TimingsHandler::tick();
|
||||
|
||||
$now = microtime(true);
|
||||
array_shift($this->tickAverage);
|
||||
$this->tickAverage[] = min(20, 1 / max(0.001, $now - $tickTime));
|
||||
array_shift($this->useAverage);
|
||||
$this->useAverage[] = min(1, ($now - $tickTime) / 0.05);
|
||||
|
||||
if(($this->nextTick - $tickTime) < -1){
|
||||
$this->nextTick = $tickTime;
|
||||
}
|
||||
$this->nextTick += 0.05;
|
||||
$this->inTick = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,6 @@ abstract class Thread extends \Thread{
|
||||
public final function start($options = PTHREADS_INHERIT_ALL){
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
return parent::start($options & ~PTHREADS_INHERIT_CLASSES);
|
||||
return parent::start($options);
|
||||
}
|
||||
}
|
@ -29,6 +29,6 @@ abstract class Worker extends \Worker{
|
||||
public final function start($options = PTHREADS_INHERIT_ALL){
|
||||
ThreadManager::getInstance()->add($this);
|
||||
|
||||
return parent::start($options & ~PTHREADS_INHERIT_CLASSES);
|
||||
return parent::start($options);
|
||||
}
|
||||
}
|
@ -29,8 +29,8 @@ class AcaciaWoodStairs extends Stair{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array($this->id, 0, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -21,30 +21,31 @@
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
|
||||
/**
|
||||
* Air block
|
||||
*/
|
||||
class Air extends Transparent{
|
||||
public $isActivable = false;
|
||||
public $breakable = false;
|
||||
public $isFlowable = true;
|
||||
public $isTransparent = true;
|
||||
public $isReplaceable = true;
|
||||
public $isPlaceable = false;
|
||||
public $hasPhysics = false;
|
||||
public $isSolid = false;
|
||||
public $isFullBlock = true;
|
||||
protected $id = self::AIR;
|
||||
protected $meta = 0;
|
||||
protected $name = "Air";
|
||||
protected $hardness = 0;
|
||||
|
||||
public function __construct(){
|
||||
parent::__construct(self::AIR, 0, "Air");
|
||||
$this->isActivable = false;
|
||||
$this->breakable = false;
|
||||
$this->isFlowable = true;
|
||||
$this->isTransparent = true;
|
||||
$this->isReplaceable = true;
|
||||
$this->isPlaceable = false;
|
||||
$this->hasPhysics = false;
|
||||
$this->isSolid = false;
|
||||
$this->isFullBlock = true;
|
||||
$this->hardness = 0;
|
||||
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return new AxisAlignedBB(0, 0, 0, 0, 0, 0);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -22,6 +22,8 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\network\protocol\ChatPacket;
|
||||
use pocketmine\Player;
|
||||
|
||||
@ -33,14 +35,30 @@ class Bed extends Transparent{
|
||||
$this->hardness = 1;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 0.5625,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
/*if($player instanceof Player and Server::getInstance()->api->time->getPhase($this->getLevel()) !== "night"){
|
||||
|
||||
$time = $this->getLevel()->getTime() % Level::TIME_FULL;
|
||||
|
||||
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
|
||||
|
||||
if($player instanceof Player and !$isNight){
|
||||
$pk = new ChatPacket;
|
||||
$pk->message = "You can only sleep at night";
|
||||
$player->dataPacket($pk);
|
||||
|
||||
return true;
|
||||
}*/
|
||||
}
|
||||
|
||||
$blockNorth = $this->getSide(2); //Gets the blocks around them
|
||||
$blockSouth = $this->getSide(3);
|
||||
@ -57,10 +75,12 @@ class Bed extends Transparent{
|
||||
$b = $blockEast;
|
||||
}elseif($blockWest->getID() === $this->id and ($blockWest->meta & 0x08) === 0x08){
|
||||
$b = $blockWest;
|
||||
}elseif($player instanceof Player){
|
||||
$pk = new ChatPacket;
|
||||
$pk->message = "This bed is incomplete";
|
||||
$player->dataPacket($pk);
|
||||
}else{
|
||||
if($player instanceof Player){
|
||||
$pk = new ChatPacket;
|
||||
$pk->message = "This bed is incomplete";
|
||||
$player->dataPacket($pk);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -78,19 +98,19 @@ class Bed extends Transparent{
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->isTransparent === false){
|
||||
$faces = array(
|
||||
$faces = [
|
||||
0 => 3,
|
||||
1 => 4,
|
||||
2 => 2,
|
||||
3 => 5,
|
||||
);
|
||||
];
|
||||
$d = $player instanceof Player ? $player->getDirection() : 0;
|
||||
$next = $this->getSide($faces[(($d + 3) % 4)]);
|
||||
$downNext = $this->getSide(0);
|
||||
if($next->isReplaceable === true and $downNext->isTransparent === false){
|
||||
$meta = (($d + 3) % 4) & 0x03;
|
||||
$this->getLevel()->setBlock($block, Block::get($this->id, $meta), true, false, true);
|
||||
$this->getLevel()->setBlock($next, Block::get($this->id, $meta | 0x08), true, false, true);
|
||||
$this->getLevel()->setBlock($block, Block::get($this->id, $meta), true, true);
|
||||
$this->getLevel()->setBlock($next, Block::get($this->id, $meta | 0x08), true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -107,34 +127,34 @@ class Bed extends Transparent{
|
||||
|
||||
if(($this->meta & 0x08) === 0x08){ //This is the Top part of bed
|
||||
if($blockNorth->getID() === $this->id and $blockNorth->meta !== 0x08){ //Checks if the block ID and meta are right
|
||||
$this->getLevel()->setBlock($blockNorth, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($blockNorth, new Air(), true, true);
|
||||
}elseif($blockSouth->getID() === $this->id and $blockSouth->meta !== 0x08){
|
||||
$this->getLevel()->setBlock($blockSouth, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($blockSouth, new Air(), true, true);
|
||||
}elseif($blockEast->getID() === $this->id and $blockEast->meta !== 0x08){
|
||||
$this->getLevel()->setBlock($blockEast, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($blockEast, new Air(), true, true);
|
||||
}elseif($blockWest->getID() === $this->id and $blockWest->meta !== 0x08){
|
||||
$this->getLevel()->setBlock($blockWest, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($blockWest, new Air(), true, true);
|
||||
}
|
||||
}else{ //Bottom Part of Bed
|
||||
if($blockNorth->getID() === $this->id and ($blockNorth->meta & 0x08) === 0x08){
|
||||
$this->getLevel()->setBlock($blockNorth, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($blockNorth, new Air(), true, true);
|
||||
}elseif($blockSouth->getID() === $this->id and ($blockSouth->meta & 0x08) === 0x08){
|
||||
$this->getLevel()->setBlock($blockSouth, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($blockSouth, new Air(), true, true);
|
||||
}elseif($blockEast->getID() === $this->id and ($blockEast->meta & 0x08) === 0x08){
|
||||
$this->getLevel()->setBlock($blockEast, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($blockEast, new Air(), true, true);
|
||||
}elseif($blockWest->getID() === $this->id and ($blockWest->meta & 0x08) === 0x08){
|
||||
$this->getLevel()->setBlock($blockWest, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($blockWest, new Air(), true, true);
|
||||
}
|
||||
}
|
||||
$this->getLevel()->setBlock($this, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($this, new Air(), true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array(Item::BED, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::BED, 0, 1],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@ -32,10 +32,14 @@ class Beetroot extends Flowable{
|
||||
$this->hardness = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === self::FARMLAND){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -46,7 +50,7 @@ class Beetroot extends Flowable{
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
$this->meta = 0x07;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true, true);
|
||||
$item->count--;
|
||||
|
||||
return true;
|
||||
@ -59,7 +63,7 @@ class Beetroot extends Flowable{
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->isTransparent === true){ //TODO: Replace with common break method
|
||||
$this->getLevel()->dropItem($this, Item::get(Item::BEETROOT_SEEDS, 0, 1));
|
||||
$this->getLevel()->setBlock($this, new Air(), false, false, true);
|
||||
$this->getLevel()->setBlock($this, new Air(), false);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
@ -67,7 +71,7 @@ class Beetroot extends Flowable{
|
||||
if(mt_rand(0, 2) == 1){
|
||||
if($this->meta < 0x07){
|
||||
++$this->meta;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
|
||||
return Level::BLOCK_UPDATE_RANDOM;
|
||||
}
|
||||
@ -82,10 +86,10 @@ class Beetroot extends Flowable{
|
||||
public function getDrops(Item $item){
|
||||
$drops = [];
|
||||
if($this->meta >= 0x07){
|
||||
$drops[] = array(Item::BEETROOT, 0, 1);
|
||||
$drops[] = array(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3));
|
||||
$drops[] = [Item::BEETROOT, 0, 1];
|
||||
$drops[] = [Item::BEETROOT_SEEDS, 0, mt_rand(0, 3)];
|
||||
}else{
|
||||
$drops[] = array(Item::BEETROOT_SEEDS, 0, 1);
|
||||
$drops[] = [Item::BEETROOT_SEEDS, 0, 1];
|
||||
}
|
||||
|
||||
return $drops;
|
||||
|
@ -29,8 +29,8 @@ class BirchWoodStairs extends Stair{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array($this->id, 0, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -24,12 +24,15 @@
|
||||
*/
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\Villager;
|
||||
use pocketmine\entity\Zombie;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\MovingObjectPosition;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\metadata\Metadatable;
|
||||
use pocketmine\metadata\MetadataValue;
|
||||
use pocketmine\Player;
|
||||
@ -230,7 +233,7 @@ abstract class Block extends Position implements Metadatable{
|
||||
const GLOWING_OBSIDIAN = 246;
|
||||
const NETHER_REACTOR = 247;
|
||||
|
||||
public static $creative = array(
|
||||
public static $creative = [
|
||||
//Building
|
||||
[Item::COBBLESTONE, 0],
|
||||
[Item::STONE_BRICKS, 0],
|
||||
@ -500,15 +503,15 @@ abstract class Block extends Position implements Metadatable{
|
||||
[Item::DYE, 9],
|
||||
[Item::DYE, 8],
|
||||
|
||||
);
|
||||
];
|
||||
|
||||
/** @var Block[] */
|
||||
public static $list = [];
|
||||
protected $id;
|
||||
protected $meta;
|
||||
protected $name;
|
||||
protected $breakTime;
|
||||
protected $hardness;
|
||||
protected $name = "Unknown";
|
||||
protected $breakTime = 0.20;
|
||||
protected $hardness = 10;
|
||||
public $isActivable = false;
|
||||
public $breakable = true;
|
||||
public $isFlowable = false;
|
||||
@ -526,144 +529,144 @@ abstract class Block extends Position implements Metadatable{
|
||||
|
||||
public static function init(){
|
||||
if(count(self::$list) === 0){
|
||||
self::$list = array(
|
||||
self::AIR => new Air(),
|
||||
self::STONE => new Stone(),
|
||||
self::GRASS => new Grass(),
|
||||
self::DIRT => new Dirt(),
|
||||
self::COBBLESTONE => new Cobblestone(),
|
||||
self::PLANKS => new Planks(),
|
||||
self::SAPLING => new Sapling(),
|
||||
self::BEDROCK => new Bedrock(),
|
||||
self::WATER => new Water(),
|
||||
self::STILL_WATER => new StillWater(),
|
||||
self::LAVA => new Lava(),
|
||||
self::STILL_LAVA => new StillLava(),
|
||||
self::SAND => new Sand(),
|
||||
self::GRAVEL => new Gravel(),
|
||||
self::GOLD_ORE => new GoldOre(),
|
||||
self::IRON_ORE => new IronOre(),
|
||||
self::COAL_ORE => new CoalOre(),
|
||||
self::WOOD => new Wood(),
|
||||
self::LEAVES => new Leaves(),
|
||||
self::SPONGE => new Sponge(),
|
||||
self::GLASS => new Glass(),
|
||||
self::LAPIS_ORE => new LapisOre(),
|
||||
self::LAPIS_BLOCK => new Lapis(),
|
||||
self::SANDSTONE => new Sandstone(),
|
||||
self::BED_BLOCK => new Bed(),
|
||||
self::COBWEB => new Cobweb(),
|
||||
self::TALL_GRASS => new TallGrass(),
|
||||
self::DEAD_BUSH => new DeadBush(),
|
||||
self::WOOL => new Wool(),
|
||||
self::DANDELION => new Dandelion(),
|
||||
self::POPPY => new CyanFlower(),
|
||||
self::BROWN_MUSHROOM => new BrownMushroom(),
|
||||
self::RED_MUSHROOM => new RedMushroom(),
|
||||
self::GOLD_BLOCK => new Gold(),
|
||||
self::IRON_BLOCK => new Iron(),
|
||||
self::DOUBLE_SLAB => new DoubleSlab(),
|
||||
self::SLAB => new Slab(),
|
||||
self::BRICKS_BLOCK => new Bricks(),
|
||||
self::TNT => new TNT(),
|
||||
self::BOOKSHELF => new Bookshelf(),
|
||||
self::MOSS_STONE => new MossStone(),
|
||||
self::OBSIDIAN => new Obsidian(),
|
||||
self::TORCH => new Torch(),
|
||||
self::FIRE => new Fire(),
|
||||
self::MONSTER_SPAWNER => new MonsterSpawner(),
|
||||
self::WOOD_STAIRS => new WoodStairs(),
|
||||
self::CHEST => new Chest(),
|
||||
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,
|
||||
|
||||
self::DIAMOND_ORE => new DiamondOre(),
|
||||
self::DIAMOND_BLOCK => new Diamond(),
|
||||
self::WORKBENCH => new Workbench(),
|
||||
self::WHEAT_BLOCK => new Wheat(),
|
||||
self::FARMLAND => new Farmland(),
|
||||
self::FURNACE => new Furnace(),
|
||||
self::BURNING_FURNACE => new BurningFurnace(),
|
||||
self::SIGN_POST => new SignPost(),
|
||||
self::WOOD_DOOR_BLOCK => new WoodDoor(),
|
||||
self::LADDER => new Ladder(),
|
||||
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::COBBLESTONE_STAIRS => new CobblestoneStairs(),
|
||||
self::WALL_SIGN => new WallSign(),
|
||||
self::COBBLESTONE_STAIRS => CobblestoneStairs::class,
|
||||
self::WALL_SIGN => WallSign::class,
|
||||
|
||||
self::IRON_DOOR_BLOCK => new IronDoor(),
|
||||
self::REDSTONE_ORE => new RedstoneOre(),
|
||||
self::GLOWING_REDSTONE_ORE => new GlowingRedstoneOre(),
|
||||
self::IRON_DOOR_BLOCK => IronDoor::class,
|
||||
self::REDSTONE_ORE => RedstoneOre::class,
|
||||
self::GLOWING_REDSTONE_ORE => GlowingRedstoneOre::class,
|
||||
|
||||
self::SNOW_LAYER => new SnowLayer(),
|
||||
self::ICE => new Ice(),
|
||||
self::SNOW_BLOCK => new Snow(),
|
||||
self::CACTUS => new Cactus(),
|
||||
self::CLAY_BLOCK => new Clay(),
|
||||
self::SUGARCANE_BLOCK => new Sugarcane(),
|
||||
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::FENCE => new Fence(),
|
||||
self::PUMPKIN => new Pumpkin(),
|
||||
self::NETHERRACK => new Netherrack(),
|
||||
self::SOUL_SAND => new SoulSand(),
|
||||
self::GLOWSTONE_BLOCK => new Glowstone(),
|
||||
self::FENCE => Fence::class,
|
||||
self::PUMPKIN => Pumpkin::class,
|
||||
self::NETHERRACK => Netherrack::class,
|
||||
self::SOUL_SAND => SoulSand::class,
|
||||
self::GLOWSTONE_BLOCK => Glowstone::class,
|
||||
|
||||
self::LIT_PUMPKIN => new LitPumpkin(),
|
||||
self::CAKE_BLOCK => new Cake(),
|
||||
self::LIT_PUMPKIN => LitPumpkin::class,
|
||||
self::CAKE_BLOCK => Cake::class,
|
||||
|
||||
self::TRAPDOOR => new Trapdoor(),
|
||||
self::TRAPDOOR => Trapdoor::class,
|
||||
|
||||
self::STONE_BRICKS => new StoneBricks(),
|
||||
self::STONE_BRICKS => StoneBricks::class,
|
||||
|
||||
self::IRON_BARS => new IronBars(),
|
||||
self::GLASS_PANE => new GlassPane(),
|
||||
self::MELON_BLOCK => new Melon(),
|
||||
self::PUMPKIN_STEM => new PumpkinStem(),
|
||||
self::MELON_STEM => new MelonStem(),
|
||||
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::FENCE_GATE => new FenceGate(),
|
||||
self::BRICK_STAIRS => new BrickStairs(),
|
||||
self::STONE_BRICK_STAIRS => new StoneBrickStairs(),
|
||||
self::FENCE_GATE => FenceGate::class,
|
||||
self::BRICK_STAIRS => BrickStairs::class,
|
||||
self::STONE_BRICK_STAIRS => StoneBrickStairs::class,
|
||||
|
||||
self::MYCELIUM => new Mycelium(),
|
||||
self::NETHER_BRICKS => new NetherBrick(),
|
||||
self::MYCELIUM => Mycelium::class,
|
||||
self::NETHER_BRICKS => NetherBrick::class,
|
||||
|
||||
self::NETHER_BRICKS_STAIRS => new NetherBrickStairs(),
|
||||
self::NETHER_BRICKS_STAIRS => NetherBrickStairs::class,
|
||||
|
||||
self::END_PORTAL => new EndPortal(),
|
||||
self::END_STONE => new EndStone(),
|
||||
self::SANDSTONE_STAIRS => new SandstoneStairs(),
|
||||
self::EMERALD_ORE => new EmeraldOre(),
|
||||
self::END_PORTAL => EndPortal::class,
|
||||
self::END_STONE => EndStone::class,
|
||||
self::SANDSTONE_STAIRS => SandstoneStairs::class,
|
||||
self::EMERALD_ORE => EmeraldOre::class,
|
||||
|
||||
self::EMERALD_BLOCK => new Emerald(),
|
||||
self::SPRUCE_WOOD_STAIRS => new SpruceWoodStairs(),
|
||||
self::BIRCH_WOOD_STAIRS => new BirchWoodStairs(),
|
||||
self::JUNGLE_WOOD_STAIRS => new JungleWoodStairs(),
|
||||
self::STONE_WALL => new StoneWall(),
|
||||
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::CARROT_BLOCK => new Carrot(),
|
||||
self::POTATO_BLOCK => new Potato(),
|
||||
self::CARROT_BLOCK => Carrot::class,
|
||||
self::POTATO_BLOCK => Potato::class,
|
||||
|
||||
self::QUARTZ_BLOCK => new Quartz(),
|
||||
self::QUARTZ_STAIRS => new QuartzStairs(),
|
||||
self::DOUBLE_WOOD_SLAB => new DoubleWoodSlab(),
|
||||
self::WOOD_SLAB => new WoodSlab(),
|
||||
self::STAINED_CLAY => new StainedClay(),
|
||||
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::LEAVES2 => new Leaves2(),
|
||||
self::WOOD2 => new Wood2(),
|
||||
self::ACACIA_WOOD_STAIRS => new AcaciaWoodStairs(),
|
||||
self::DARK_OAK_WOOD_STAIRS => new DarkOakWoodStairs(),
|
||||
self::LEAVES2 => Leaves2::class,
|
||||
self::WOOD2 => Wood2::class,
|
||||
self::ACACIA_WOOD_STAIRS => AcaciaWoodStairs::class,
|
||||
self::DARK_OAK_WOOD_STAIRS => DarkOakWoodStairs::class,
|
||||
|
||||
self::HAY_BALE => new HayBale(),
|
||||
self::CARPET => new Carpet(),
|
||||
self::HARDENED_CLAY => new HardenedClay(),
|
||||
self::COAL_BLOCK => new Coal(),
|
||||
self::HAY_BALE => HayBale::class,
|
||||
self::CARPET => Carpet::class,
|
||||
self::HARDENED_CLAY => HardenedClay::class,
|
||||
self::COAL_BLOCK => Coal::class,
|
||||
|
||||
self::PODZOL => new Podzol(),
|
||||
self::BEETROOT_BLOCK => new Beetroot(),
|
||||
self::STONECUTTER => new Stonecutter(),
|
||||
self::GLOWING_OBSIDIAN => new GlowingObsidian(),
|
||||
self::NETHER_REACTOR => new NetherReactor(),
|
||||
);
|
||||
self::PODZOL => Podzol::class,
|
||||
self::BEETROOT_BLOCK => Beetroot::class,
|
||||
self::STONECUTTER => Stonecutter::class,
|
||||
self::GLOWING_OBSIDIAN => GlowingObsidian::class,
|
||||
self::NETHER_REACTOR => NetherReactor::class,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -676,11 +679,12 @@ abstract class Block extends Position implements Metadatable{
|
||||
*/
|
||||
public static function get($id, $meta = 0, Position $pos = null){
|
||||
if(isset(self::$list[$id])){
|
||||
$block = clone self::$list[$id];
|
||||
$block->setDamage($meta);
|
||||
$block = self::$list[$id];
|
||||
$block = new $block($meta);
|
||||
}else{
|
||||
$block = new Generic($id, $meta);
|
||||
}
|
||||
|
||||
if($pos instanceof Position){
|
||||
$block->position($pos);
|
||||
}
|
||||
@ -697,8 +701,6 @@ abstract class Block extends Position implements Metadatable{
|
||||
$this->id = (int) $id;
|
||||
$this->meta = (int) $meta;
|
||||
$this->name = $name;
|
||||
$this->breakTime = 0.20;
|
||||
$this->hardness = 10;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -760,7 +762,7 @@ abstract class Block extends Position implements Metadatable{
|
||||
return [];
|
||||
}else{
|
||||
return [
|
||||
array($this->id, $this->meta, 1),
|
||||
[$this->id, $this->meta, 1],
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -824,13 +826,20 @@ abstract class Block extends Position implements Metadatable{
|
||||
* @param AxisAlignedBB $bb
|
||||
* @param Block[] $list
|
||||
*/
|
||||
public function collidesWithBB(AxisAlignedBB $bb, &$list = array()){
|
||||
public function collidesWithBB(AxisAlignedBB $bb, &$list = []){
|
||||
$bb2 = $this->getBoundingBox();
|
||||
if($bb2->intersectsWith($bb)){
|
||||
if($bb2 !== null and $bb2->intersectsWith($bb)){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
*/
|
||||
public function onEntityCollide(Entity $entity){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB
|
||||
*/
|
||||
@ -845,6 +854,88 @@ abstract class Block extends Position implements Metadatable{
|
||||
);
|
||||
}
|
||||
|
||||
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2){
|
||||
$bb = $this->getBoundingBox();
|
||||
if($bb === null){
|
||||
return null;
|
||||
}
|
||||
|
||||
$v1 = $pos1->getIntermediateWithXValue($pos2, $bb->minX);
|
||||
$v2 = $pos1->getIntermediateWithXValue($pos2, $bb->maxX);
|
||||
$v3 = $pos1->getIntermediateWithYValue($pos2, $bb->minY);
|
||||
$v4 = $pos1->getIntermediateWithYValue($pos2, $bb->maxY);
|
||||
$v5 = $pos1->getIntermediateWithZValue($pos2, $bb->minZ);
|
||||
$v6 = $pos1->getIntermediateWithZValue($pos2, $bb->maxZ);
|
||||
|
||||
if($v1 !== null and !$bb->isVectorInYZ($v1)){
|
||||
$v1 = null;
|
||||
}
|
||||
|
||||
if($v2 !== null and !$bb->isVectorInYZ($v2)){
|
||||
$v2 = null;
|
||||
}
|
||||
|
||||
if($v3 !== null and !$bb->isVectorInXZ($v3)){
|
||||
$v3 = null;
|
||||
}
|
||||
|
||||
if($v4 !== null and !$bb->isVectorInXZ($v4)){
|
||||
$v4 = null;
|
||||
}
|
||||
|
||||
if($v5 !== null and !$bb->isVectorInXY($v5)){
|
||||
$v5 = null;
|
||||
}
|
||||
|
||||
if($v6 !== null and !$bb->isVectorInXY($v6)){
|
||||
$v6 = null;
|
||||
}
|
||||
|
||||
$vector = $v1;
|
||||
|
||||
if($v2 !== null and ($vector === null or $pos1->distanceSquared($v2) < $pos1->distanceSquared($vector))){
|
||||
$vector = $v2;
|
||||
}
|
||||
|
||||
if($v3 !== null and ($vector === null or $pos1->distanceSquared($v3) < $pos1->distanceSquared($vector))){
|
||||
$vector = $v3;
|
||||
}
|
||||
|
||||
if($v4 !== null and ($vector === null or $pos1->distanceSquared($v4) < $pos1->distanceSquared($vector))){
|
||||
$vector = $v4;
|
||||
}
|
||||
|
||||
if($v5 !== null and ($vector === null or $pos1->distanceSquared($v5) < $pos1->distanceSquared($vector))){
|
||||
$vector = $v5;
|
||||
}
|
||||
|
||||
if($v6 !== null and ($vector === null or $pos1->distanceSquared($v6) < $pos1->distanceSquared($vector))){
|
||||
$vector = $v6;
|
||||
}
|
||||
|
||||
if($vector === null){
|
||||
return null;
|
||||
}
|
||||
|
||||
$f = -1;
|
||||
|
||||
if($vector === $v1){
|
||||
$f = 4;
|
||||
}elseif($vector === $v2){
|
||||
$f = 5;
|
||||
}elseif($vector === $v3){
|
||||
$f = 0;
|
||||
}elseif($vector === $v4){
|
||||
$f = 1;
|
||||
}elseif($vector === $v5){
|
||||
$f = 2;
|
||||
}elseif($vector === $v6){
|
||||
$f = 3;
|
||||
}
|
||||
|
||||
return MovingObjectPosition::fromBlock($this->x, $this->y, $this->z, $f, $vector->add($this->x, $this->y, $this->z));
|
||||
}
|
||||
|
||||
/**
|
||||
* Places the Block, using block space and block target, and side. Returns if the block has been placed.
|
||||
*
|
||||
|
@ -48,9 +48,9 @@ class Bricks extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::BRICKS_BLOCK, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::BRICKS_BLOCK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -47,11 +47,16 @@ class BrownMushroom extends Flowable{
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->isTransparent === false){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -39,21 +39,21 @@ class BurningFurnace extends Solid{
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$faces = array(
|
||||
$faces = [
|
||||
0 => 4,
|
||||
1 => 2,
|
||||
2 => 5,
|
||||
3 => 3,
|
||||
);
|
||||
];
|
||||
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$nbt = new Compound(false, array(
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
$nbt = new Compound(false, [
|
||||
new Enum("Items", []),
|
||||
new String("id", Tile::FURNACE),
|
||||
new Int("x", $this->x),
|
||||
new Int("y", $this->y),
|
||||
new Int("z", $this->z)
|
||||
));
|
||||
]);
|
||||
$nbt->Items->setTagType(NBT::TAG_Compound);
|
||||
new Furnace($this->getLevel()->getChunkAt($this->x >> 4, $this->z >> 4), $nbt);
|
||||
|
||||
@ -73,13 +73,13 @@ class BurningFurnace extends Solid{
|
||||
if($t instanceof Furnace){
|
||||
$furnace = $t;
|
||||
}else{
|
||||
$nbt = new Compound(false, array(
|
||||
$nbt = new Compound(false, [
|
||||
new Enum("Items", []),
|
||||
new String("id", Tile::FURNACE),
|
||||
new Int("x", $this->x),
|
||||
new Int("y", $this->y),
|
||||
new Int("z", $this->z)
|
||||
));
|
||||
]);
|
||||
$nbt->Items->setTagType(NBT::TAG_Compound);
|
||||
$furnace = new Furnace($this->getLevel()->getChunkAt($this->x >> 4, $this->z >> 4), $nbt);
|
||||
}
|
||||
@ -114,14 +114,14 @@ class BurningFurnace extends Solid{
|
||||
public function getDrops(Item $item){
|
||||
$drops = [];
|
||||
if($item->isPickaxe() >= 1){
|
||||
$drops[] = array(Item::FURNACE, 0, 1);
|
||||
$drops[] = [Item::FURNACE, 0, 1];
|
||||
}
|
||||
$t = $this->getLevel()->getTile($this);
|
||||
if($t instanceof Furnace){
|
||||
for($s = 0; $s < $t->getInventory()->getSize(); ++$s){
|
||||
$slot = $t->getInventory()->getItem($s);
|
||||
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
|
||||
$drops[] = array($slot->getID(), $slot->getDamage(), $slot->getCount());
|
||||
$drops[] = [$slot->getID(), $slot->getDamage(), $slot->getCount()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,12 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3 as Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\Server;
|
||||
|
||||
class Cactus extends Transparent{
|
||||
public function __construct($meta = 0){
|
||||
@ -33,6 +37,25 @@ class Cactus extends Transparent{
|
||||
$this->hardness = 2;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 0.0625,
|
||||
$this->y,
|
||||
$this->z + 0.0625,
|
||||
$this->x + 0.9375,
|
||||
$this->y + 1,
|
||||
$this->z + 0.9375
|
||||
);
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
$ev = new EntityDamageEvent($entity, EntityDamageEvent::CAUSE_CONTACT, 1);
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
||||
if(!$ev->isCancelled()){
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
$down = $this->getSide(0);
|
||||
@ -40,7 +63,17 @@ class Cactus extends Transparent{
|
||||
$this->getLevel()->setBlock($this, new Air(), false);
|
||||
$this->getLevel()->dropItem($this, Item::get($this->id));
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
return;
|
||||
}else{
|
||||
for($side = 2; $side <= 5; ++$side){
|
||||
$b = $this->getSide($side);
|
||||
if(!$b->isFlowable){
|
||||
$this->getLevel()->setBlock($this, new Air(), false);
|
||||
$this->getLevel()->dropItem($this, Item::get($this->id));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
if($this->getSide(0)->getID() !== self::CACTUS){
|
||||
@ -48,18 +81,18 @@ class Cactus extends Transparent{
|
||||
for($y = 1; $y < 3; ++$y){
|
||||
$b = $this->getLevel()->getBlock(new Vector3($this->x, $this->y + $y, $this->z));
|
||||
if($b->getID() === self::AIR){
|
||||
$this->getLevel()->setBlock($b, new Cactus(), true, false, true);
|
||||
$this->getLevel()->setBlock($b, new Cactus(), true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->meta = 0;
|
||||
$this->getLevel()->setBlock($this, $this, false);
|
||||
$this->getLevel()->setBlock($this, $this);
|
||||
}else{
|
||||
++$this->meta;
|
||||
$this->getLevel()->setBlock($this, $this, false);
|
||||
$this->getLevel()->setBlock($this, $this);
|
||||
}
|
||||
|
||||
return Level::BLOCK_UPDATE_RANDOM;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,7 +107,7 @@ class Cactus extends Transparent{
|
||||
$block2 = $this->getSide(4);
|
||||
$block3 = $this->getSide(5);
|
||||
if($block0->isTransparent === true and $block1->isTransparent === true and $block2->isTransparent === true and $block3->isTransparent === true){
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -84,8 +117,8 @@ class Cactus extends Transparent{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array($this->id, 0, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Cake extends Transparent{
|
||||
@ -34,10 +35,23 @@ class Cake extends Transparent{
|
||||
$this->hardness = 2.5;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
$f = (1 + $this->getDamage() * 2) / 16;
|
||||
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $f,
|
||||
$this->y,
|
||||
$this->z + 0.0625,
|
||||
$this->x + 1 - 0.0625,
|
||||
$this->y + 0.5,
|
||||
$this->z + 1 - 0.0625
|
||||
);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() !== self::AIR){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -48,7 +62,7 @@ class Cake extends Transparent{
|
||||
public function onUpdate($type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->getID() === self::AIR){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($this, new Air(), true);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
@ -66,9 +80,9 @@ class Cake extends Transparent{
|
||||
++$this->meta;
|
||||
$player->heal(3, "cake");
|
||||
if($this->meta >= 0x06){
|
||||
$this->getLevel()->setBlock($this, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($this, new Air(), true);
|
||||
}else{
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -23,12 +23,13 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Carpet extends Flowable{
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::CARPET, $meta, "Carpet");
|
||||
$names = array(
|
||||
$names = [
|
||||
0 => "White Carpet",
|
||||
1 => "Orange Carpet",
|
||||
2 => "Magenta Carpet",
|
||||
@ -45,17 +46,28 @@ class Carpet extends Flowable{
|
||||
13 => "Green Carpet",
|
||||
14 => "Red Carpet",
|
||||
15 => "Black Carpet",
|
||||
);
|
||||
];
|
||||
$this->name = $names[$this->meta];
|
||||
$this->hardness = 0;
|
||||
$this->isFullBlock = false;
|
||||
$this->isSolid = true;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 0.0625,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() !== self::AIR){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -67,7 +79,7 @@ class Carpet extends Flowable{
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->getID() === self::AIR){ //TODO: Replace with common break method
|
||||
$this->getLevel()->dropItem($this, Item::get($this->id, $this->meta, 1));
|
||||
$this->getLevel()->setBlock($this, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($this, new Air(), true);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
|
@ -32,10 +32,15 @@ class Carrot extends Flowable{
|
||||
$this->hardness = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === self::FARMLAND){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -46,7 +51,7 @@ class Carrot extends Flowable{
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
$this->meta = 0x07;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
$item->count--;
|
||||
|
||||
return true;
|
||||
@ -68,7 +73,7 @@ class Carrot extends Flowable{
|
||||
if(mt_rand(0, 2) == 1){
|
||||
if($this->meta < 0x07){
|
||||
++$this->meta;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
|
||||
return Level::BLOCK_UPDATE_RANDOM;
|
||||
}
|
||||
@ -83,9 +88,9 @@ class Carrot extends Flowable{
|
||||
public function getDrops(Item $item){
|
||||
$drops = [];
|
||||
if($this->meta >= 0x07){
|
||||
$drops[] = array(Item::CARROT, 0, mt_rand(1, 4));
|
||||
$drops[] = [Item::CARROT, 0, mt_rand(1, 4)];
|
||||
}else{
|
||||
$drops[] = array(Item::CARROT, 0, 1);
|
||||
$drops[] = [Item::CARROT, 0, 1];
|
||||
}
|
||||
|
||||
return $drops;
|
||||
|
@ -22,6 +22,7 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\nbt\NBT;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Enum;
|
||||
@ -41,13 +42,24 @@ class Chest extends Transparent{
|
||||
$this->hardness = 15;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 0.0625,
|
||||
$this->y,
|
||||
$this->z + 0.0625,
|
||||
$this->x + 0.9375,
|
||||
$this->y + 0.875,
|
||||
$this->z + 0.9375
|
||||
);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$faces = array(
|
||||
$faces = [
|
||||
0 => 4,
|
||||
1 => 2,
|
||||
2 => 5,
|
||||
3 => 3,
|
||||
);
|
||||
];
|
||||
|
||||
$chest = false;
|
||||
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
|
||||
@ -68,14 +80,14 @@ class Chest extends Transparent{
|
||||
}
|
||||
}
|
||||
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$nbt = new Compound(false, array(
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
$nbt = new Compound(false, [
|
||||
new Enum("Items", []),
|
||||
new String("id", Tile::CHEST),
|
||||
new Int("x", $this->x),
|
||||
new Int("y", $this->y),
|
||||
new Int("z", $this->z)
|
||||
));
|
||||
]);
|
||||
$nbt->Items->setTagType(NBT::TAG_Compound);
|
||||
$tile = new TileChest($this->getLevel()->getChunkAt($this->x >> 4, $this->z >> 4), $nbt);
|
||||
|
||||
@ -109,13 +121,13 @@ class Chest extends Transparent{
|
||||
if($t instanceof TileChest){
|
||||
$chest = $t;
|
||||
}else{
|
||||
$nbt = new Compound(false, array(
|
||||
$nbt = new Compound(false, [
|
||||
new Enum("Items", []),
|
||||
new String("id", Tile::CHEST),
|
||||
new Int("x", $this->x),
|
||||
new Int("y", $this->y),
|
||||
new Int("z", $this->z)
|
||||
));
|
||||
]);
|
||||
$nbt->Items->setTagType(NBT::TAG_Compound);
|
||||
$chest = new TileChest($this->getLevel()->getChunkAt($this->x >> 4, $this->z >> 4), $nbt);
|
||||
}
|
||||
@ -131,15 +143,15 @@ class Chest extends Transparent{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
$drops = array(
|
||||
array($this->id, 0, 1),
|
||||
);
|
||||
$drops = [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
$t = $this->getLevel()->getTile($this);
|
||||
if($t instanceof TileChest){
|
||||
for($s = 0; $s < $t->getRealInventory()->getSize(); ++$s){
|
||||
$slot = $t->getRealInventory()->getItem($s);
|
||||
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
|
||||
$drops[] = array($slot->getID(), $slot->getDamage(), $slot->getCount());
|
||||
$drops[] = [$slot->getID(), $slot->getDamage(), $slot->getCount()];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ class Clay extends Solid{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array(Item::CLAY, 0, 4),
|
||||
);
|
||||
return [
|
||||
[Item::CLAY, 0, 4],
|
||||
];
|
||||
}
|
||||
}
|
@ -48,9 +48,9 @@ class Coal extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::COAL_BLOCK, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::COAL_BLOCK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -48,9 +48,9 @@ class CoalOre extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::COAL, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::COAL, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -48,9 +48,9 @@ class Cobblestone extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::COBBLESTONE, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::COBBLESTONE, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\entity\Entity;
|
||||
|
||||
class Cobweb extends Flowable{
|
||||
public function __construct(){
|
||||
@ -31,6 +32,10 @@ class Cobweb extends Flowable{
|
||||
$this->hardness = 25;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
$entity->fallDistance = 0;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return [];
|
||||
}
|
||||
|
@ -31,10 +31,15 @@ class CyanFlower extends Flowable{
|
||||
$this->hardness = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === 2 or $down->getID() === 3 or $down->getID() === 60){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -31,10 +31,15 @@ class Dandelion extends Flowable{
|
||||
$this->hardness = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === 2 or $down->getID() === 3 or $down->getID() === 60){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ class DarkOakWoodStairs extends Stair{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array($this->id, 0, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -30,6 +30,11 @@ class DeadBush extends Flowable{
|
||||
$this->hardness = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function onUpdate($type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->isTransparent === true){ //Replace with common break method
|
||||
|
@ -42,9 +42,9 @@ class Diamond extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 4){
|
||||
return array(
|
||||
array(Item::DIAMOND_BLOCK, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::DIAMOND_BLOCK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -42,9 +42,9 @@ class DiamondOre extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 4){
|
||||
return array(
|
||||
array(Item::DIAMOND, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::DIAMOND, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -25,16 +25,21 @@ use pocketmine\item\Item;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Dirt extends Solid{
|
||||
|
||||
public $isActivable = true;
|
||||
protected $hardness = 2.5;
|
||||
protected $id = self::DIRT;
|
||||
protected $meta = 0;
|
||||
protected $name = "Dirt";
|
||||
|
||||
public function __construct(){
|
||||
parent::__construct(self::DIRT, 0, "Dirt");
|
||||
$this->isActivable = true;
|
||||
$this->hardness = 2.5;
|
||||
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
if($item->isHoe()){
|
||||
$item->useOn($this);
|
||||
$this->getLevel()->setBlock($this, Block::get(Item::FARMLAND, 0), true, false, true);
|
||||
$this->getLevel()->setBlock($this, Block::get(Item::FARMLAND, 0), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\network\protocol\LevelEventPacket;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
@ -34,6 +35,169 @@ abstract class Door extends Transparent{
|
||||
$this->isSolid = false;
|
||||
}
|
||||
|
||||
private function getFullDamage(){
|
||||
$damage = $this->getDamage();
|
||||
$flag = ($damage & 0x08) > 0;
|
||||
|
||||
if($flag){
|
||||
$first = $this->getSide(0)->getDamage();
|
||||
$second = $damage;
|
||||
}else{
|
||||
$first = $damage;
|
||||
$second = $this->getSide(1)->getDamage();
|
||||
}
|
||||
|
||||
$flag1 = ($second & 0x01) > 0;
|
||||
|
||||
return $first & 0x07 | ($flag ? 8 : 0) | ($flag1 ? 0x10 : 0);
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
$f = 0.1875;
|
||||
$damage = $this->getFullDamage();
|
||||
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 2,
|
||||
$this->z + 1
|
||||
);
|
||||
|
||||
$j = $damage & 0x03;
|
||||
$flag = (($damage & 0x04) > 0);
|
||||
$flag1 = (($damage & 0x10) > 0);
|
||||
|
||||
if($j === 0){
|
||||
if($flag){
|
||||
if(!$flag1){
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + $f
|
||||
);
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 1 - $f,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + $f,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}elseif($j === 1){
|
||||
if($flag){
|
||||
if(!$flag1){
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x + 1 - $f,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + $f,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + $f
|
||||
);
|
||||
}
|
||||
}elseif($j === 2){
|
||||
if($flag){
|
||||
if(!$flag1){
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 1 - $f,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + $f
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x + 1 - $f,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}elseif($j === 3){
|
||||
if($flag){
|
||||
if(!$flag1){
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + $f,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x + 1 - $f,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}else{
|
||||
$bb = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 1 - $f,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $bb;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->getID() === self::AIR){ //Replace with common break method
|
||||
@ -57,22 +221,22 @@ abstract class Door extends Transparent{
|
||||
return false;
|
||||
}
|
||||
$direction = $player instanceof Player ? $player->getDirection() : 0;
|
||||
$face = array(
|
||||
$face = [
|
||||
0 => 3,
|
||||
1 => 4,
|
||||
2 => 2,
|
||||
3 => 5,
|
||||
);
|
||||
];
|
||||
$next = $this->getSide($face[(($direction + 2) % 4)]);
|
||||
$next2 = $this->getSide($face[$direction]);
|
||||
$metaUp = 0x08;
|
||||
if($next->getID() === $this->id or ($next2->isTransparent === false and $next->isTransparent === true)){ //Door hinge
|
||||
$metaUp |= 0x01;
|
||||
}
|
||||
$this->getLevel()->setBlock($blockUp, Block::get($this->id, $metaUp), true, false, true); //Top
|
||||
|
||||
$this->meta = $player->getDirection() & 0x03;
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true); //Bottom
|
||||
$this->getLevel()->setBlock($block, $this, true, true); //Bottom
|
||||
$this->getLevel()->setBlock($blockUp, $b = Block::get($this->id, $metaUp), true); //Top
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -83,15 +247,15 @@ abstract class Door extends Transparent{
|
||||
if(($this->meta & 0x08) === 0x08){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === $this->id){
|
||||
$this->getLevel()->setBlock($down, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($down, new Air(), true);
|
||||
}
|
||||
}else{
|
||||
$up = $this->getSide(1);
|
||||
if($up->getID() === $this->id){
|
||||
$this->getLevel()->setBlock($up, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($up, new Air(), true);
|
||||
}
|
||||
}
|
||||
$this->getLevel()->setBlock($this, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($this, new Air(), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -101,7 +265,7 @@ abstract class Door extends Transparent{
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === $this->id){
|
||||
$meta = $down->getDamage() ^ 0x04;
|
||||
$this->getLevel()->setBlock($down, Block::get($this->id, $meta), true, false, true);
|
||||
$this->getLevel()->setBlock($down, Block::get($this->id, $meta), true);
|
||||
$players = $this->getLevel()->getUsingChunk($this->x >> 4, $this->z >> 4);
|
||||
if($player instanceof Player){
|
||||
unset($players[$player->getID()]);
|
||||
@ -120,7 +284,7 @@ abstract class Door extends Transparent{
|
||||
return false;
|
||||
}else{
|
||||
$this->meta ^= 0x04;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
$players = $this->getLevel()->getUsingChunk($this->x >> 4, $this->z >> 4);
|
||||
if($player instanceof Player){
|
||||
unset($players[$player->getID()]);
|
||||
|
@ -26,7 +26,7 @@ use pocketmine\item\Item;
|
||||
class DoubleSlab extends Solid{
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::DOUBLE_SLAB, $meta, "Double Slab");
|
||||
$names = array(
|
||||
$names = [
|
||||
0 => "Stone",
|
||||
1 => "Sandstone",
|
||||
2 => "Wooden",
|
||||
@ -34,7 +34,8 @@ class DoubleSlab extends Solid{
|
||||
4 => "Brick",
|
||||
5 => "Stone Brick",
|
||||
6 => "Quartz",
|
||||
);
|
||||
7 => "",
|
||||
];
|
||||
$this->name = "Double " . $names[$this->meta & 0x07] . " Slab";
|
||||
$this->hardness = 30;
|
||||
}
|
||||
@ -58,9 +59,9 @@ class DoubleSlab extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::SLAB, $this->meta & 0x07, 2),
|
||||
);
|
||||
return [
|
||||
[Item::SLAB, $this->meta & 0x07, 2],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -26,14 +26,14 @@ use pocketmine\item\Item;
|
||||
class DoubleWoodSlab extends Solid{
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::DOUBLE_WOOD_SLAB, $meta, "Double Wooden Slab");
|
||||
$names = array(
|
||||
$names = [
|
||||
0 => "Oak",
|
||||
1 => "Spruce",
|
||||
2 => "Birch",
|
||||
3 => "Jungle",
|
||||
4 => "Acacia",
|
||||
5 => "Dark Oak",
|
||||
);
|
||||
];
|
||||
$this->name = "Double " . $names[$this->meta & 0x07] . " Wooden Slab";
|
||||
$this->hardness = 15;
|
||||
}
|
||||
@ -56,9 +56,9 @@ class DoubleWoodSlab extends Solid{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array(Item::WOOD_SLAB, $this->meta & 0x07, 2),
|
||||
);
|
||||
return [
|
||||
[Item::WOOD_SLAB, $this->meta & 0x07, 2],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@ -42,9 +42,9 @@ class Emerald extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 4){
|
||||
return array(
|
||||
array(Item::EMERALD_BLOCK, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::EMERALD_BLOCK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -42,9 +42,9 @@ class EmeraldOre extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 4){
|
||||
return array(
|
||||
array(Item::EMERALD, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::EMERALD, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -21,11 +21,22 @@
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
class EndPortal extends Solid{
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::END_PORTAL, $meta, "End Portal");
|
||||
$this->hardness = 18000000;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + (($this->getDamage() & 0x04) > 0 ? 1 : 0.8125),
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}
|
@ -23,17 +23,51 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\entity\FallingBlock;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Enum;
|
||||
use pocketmine\nbt\tag\Double;
|
||||
use pocketmine\nbt\tag\Float;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
|
||||
class Fallable extends Solid{
|
||||
|
||||
public function __construct($id, $meta = 0, $name = "Unknown"){
|
||||
parent::__construct($id, $meta, $name);
|
||||
$this->hasPhysics = true;
|
||||
}
|
||||
public $hasPhysics = true;
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$ret = $this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$ret = $this->getLevel()->setBlock($this, $this, true, true);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
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()->getChunkAt($this->x >> 4, $this->z >> 4), new Compound("", [
|
||||
"Pos" => new Enum("Pos", [
|
||||
new Double("", $this->x + 0.5),
|
||||
new Double("", $this->y + 0.5),
|
||||
new Double("", $this->z + 0.5)
|
||||
]),
|
||||
//TODO: add random motion with physics
|
||||
"Motion" => new Enum("Motion", [
|
||||
new Double("", 0),
|
||||
new Double("", 0),
|
||||
new Double("", 0)
|
||||
]),
|
||||
"Rotation" => new Enum("Rotation", [
|
||||
new Float("", 0),
|
||||
new Float("", 0)
|
||||
]),
|
||||
"Tile" => new Byte("Tile", $this->getID())
|
||||
]));
|
||||
|
||||
$fall->spawnToAll();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
class Farmland extends Solid{
|
||||
public function __construct($meta = 0){
|
||||
@ -29,9 +30,20 @@ class Farmland extends Solid{
|
||||
$this->hardness = 3;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array(Item::DIRT, 0, 1),
|
||||
public function getBoundingBox(){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 0.9375,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return [
|
||||
[Item::DIRT, 0, 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -22,6 +22,9 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
class Fence extends Transparent{
|
||||
public function __construct(){
|
||||
parent::__construct(self::FENCE, 0, "Fence");
|
||||
@ -29,4 +32,29 @@ class Fence extends Transparent{
|
||||
$this->hardness = 15;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
$flag = $this->canConnect($this->getSide(2));
|
||||
$flag1 = $this->canConnect($this->getSide(3));
|
||||
$flag2 = $this->canConnect($this->getSide(4));
|
||||
$flag3 = $this->canConnect($this->getSide(5));
|
||||
|
||||
$f = $flag2 ? 0 : 0.375;
|
||||
$f1 = $flag3 ? 1 : 0.625;
|
||||
$f2 = $flag ? 0 : 0.375;
|
||||
$f3 = $flag1 ? 1 : 0.625;
|
||||
|
||||
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->z + $f3
|
||||
);
|
||||
}
|
||||
|
||||
public function canConnect(Block $block){
|
||||
return ($block->getID() !== self::FENCE and $block->getID() !== self::FENCE_GATE) ? $block->isSolid : true;
|
||||
}
|
||||
|
||||
}
|
@ -22,6 +22,7 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\Player;
|
||||
|
||||
class FenceGate extends Transparent{
|
||||
@ -36,39 +37,67 @@ class FenceGate extends Transparent{
|
||||
$this->hardness = 15;
|
||||
}
|
||||
|
||||
|
||||
public function getBoundingBox(){
|
||||
if(($this->getDamage() & 0x04) > 0){
|
||||
return null;
|
||||
}
|
||||
|
||||
$i = ($this->getDamage() & 0x03);
|
||||
if($i === 2 and $i === 0){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 0.375,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 0.625
|
||||
);
|
||||
}else{
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 0.375,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 0.625,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$faces = array(
|
||||
$faces = [
|
||||
0 => 3,
|
||||
1 => 0,
|
||||
2 => 1,
|
||||
3 => 2,
|
||||
);
|
||||
];
|
||||
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0] & 0x03;
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array($this->id, 0, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
$faces = array(
|
||||
$faces = [
|
||||
0 => 3,
|
||||
1 => 0,
|
||||
2 => 1,
|
||||
3 => 2,
|
||||
);
|
||||
];
|
||||
$this->meta = ($faces[$player instanceof Player ? $player->getDirection() : 0] & 0x03) | ((~$this->meta) & 0x04);
|
||||
if(($this->meta & 0x04) === 0x04){
|
||||
$this->isFullBlock = true;
|
||||
}else{
|
||||
$this->isFullBlock = false;
|
||||
}
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -22,7 +22,10 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\Server;
|
||||
|
||||
class Fire extends Flowable{
|
||||
public function __construct($meta = 0){
|
||||
@ -33,6 +36,19 @@ class Fire extends Flowable{
|
||||
$this->hardness = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
$entity->setOnFire(8);
|
||||
$ev = new EntityDamageEvent($entity, EntityDamageEvent::CAUSE_FIRE, 1);
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
||||
if(!$ev->isCancelled()){
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return [];
|
||||
}
|
||||
@ -45,12 +61,12 @@ class Fire extends Flowable{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$this->getLevel()->setBlock($this, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($this, new Air(), true);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
if($this->getSide(0)->getID() !== self::NETHERRACK){
|
||||
$this->getLevel()->setBlock($this, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($this, new Air(), true);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
|
@ -23,10 +23,9 @@ namespace pocketmine\block;
|
||||
|
||||
|
||||
class Flowable extends Transparent{
|
||||
public function __construct($id, $meta = 0, $name = "Unknown"){
|
||||
parent::__construct($id, $meta, $name);
|
||||
$this->isFlowable = true;
|
||||
$this->isFullBlock = false;
|
||||
$this->isSolid = false;
|
||||
}
|
||||
|
||||
public $isFlowable = true;
|
||||
public $isFullBlock = false;
|
||||
public $isSolid = false;
|
||||
|
||||
}
|
@ -27,17 +27,8 @@ use pocketmine\Player;
|
||||
|
||||
class Generic extends Block{
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param int $meta
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct($id, $meta = 0, $name = "Unknown"){
|
||||
parent::__construct($id, $meta, $name);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
return $this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
return $this->getLevel()->setBlock($this, $this, true, true);
|
||||
}
|
||||
|
||||
public function isBreakable(Item $item){
|
||||
@ -45,29 +36,10 @@ class Generic extends Block{
|
||||
}
|
||||
|
||||
public function onBreak(Item $item){
|
||||
return $this->getLevel()->setBlock($this, new Air(), true, false, true);
|
||||
return $this->getLevel()->setBlock($this, new Air(), true, true);
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
if($this->hasPhysics === true and $type === Level::BLOCK_UPDATE_NORMAL){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === self::AIR or ($down instanceof Liquid)){
|
||||
$data = array(
|
||||
"x" => $this->x + 0.5,
|
||||
"y" => $this->y + 0.5,
|
||||
"z" => $this->z + 0.5,
|
||||
"Tile" => $this->id,
|
||||
);
|
||||
/*$this->getLevel()->setBlock($this, new Air(), false, false, true);
|
||||
//TODO
|
||||
//$e = $server->api->entity->add($this->getLevel(), ENTITY_FALLING, FALLING_SAND, $data);
|
||||
//$e->spawnToAll();
|
||||
$server->api->block->blockUpdateAround(clone $this, Level::BLOCK_UPDATE_NORMAL, 1);*/
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -22,11 +22,9 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class GlassPane extends Transparent{
|
||||
class GlassPane extends Thin{
|
||||
public function __construct(){
|
||||
parent::__construct(self::GLASS_PANE, 0, "Glass Pane");
|
||||
$this->isFullBlock = false;
|
||||
$this->isSolid = false;
|
||||
}
|
||||
|
||||
}
|
@ -54,9 +54,9 @@ class GlowingRedstoneOre extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 4){
|
||||
return array(
|
||||
array(Item::REDSTONE_DUST, 0, mt_rand(4, 5)),
|
||||
);
|
||||
return [
|
||||
[Item::REDSTONE_DUST, 0, mt_rand(4, 5)],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ class Glowstone extends Transparent{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array(Item::GLOWSTONE_DUST, 0, mt_rand(2, 4)),
|
||||
);
|
||||
return [
|
||||
[Item::GLOWSTONE_DUST, 0, mt_rand(2, 4)],
|
||||
];
|
||||
}
|
||||
}
|
@ -42,9 +42,9 @@ class Gold extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 4){
|
||||
return array(
|
||||
array(Item::GOLD_BLOCK, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::GOLD_BLOCK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -42,9 +42,9 @@ class GoldOre extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 4){
|
||||
return array(
|
||||
array(Item::GOLD_ORE, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::GOLD_ORE, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -22,17 +22,22 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\generator\object\TallGrass;
|
||||
use pocketmine\level\generator\object\TallGrass as TallGrassObject;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\Random;
|
||||
|
||||
class Grass extends Solid{
|
||||
|
||||
public $isActivable = true;
|
||||
protected $hardness = 3;
|
||||
protected $id = self::GRASS;
|
||||
protected $meta = 0;
|
||||
protected $name = "Grass";
|
||||
|
||||
public function __construct(){
|
||||
parent::__construct(self::GRASS, 0, "Grass");
|
||||
$this->isActivable = true;
|
||||
$this->hardness = 3;
|
||||
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
@ -49,7 +54,7 @@ class Grass extends Solid{
|
||||
$z = mt_rand($this->z - 1, $this->z + 1);
|
||||
$block = $this->getLevel()->getBlockIdAt($x, $y, $z);
|
||||
if($block === Block::DIRT){
|
||||
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
|
||||
$block = Block::get($block, $this->getLevel()->getBlockDataAt($x, $y, $z), new Position($x, $y, $z, $this->getLevel()));
|
||||
if($block->getSide(1) instanceof Transparent){
|
||||
$this->getLevel()->setBlock($block, new Grass());
|
||||
}
|
||||
@ -60,7 +65,7 @@ class Grass extends Solid{
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){
|
||||
$item->count--;
|
||||
TallGrass::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2);
|
||||
TallGrassObject::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2);
|
||||
|
||||
return true;
|
||||
}elseif($item->isHoe()){
|
||||
|
@ -31,14 +31,14 @@ class Gravel extends Fallable{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if(mt_rand(1, 10) === 1){
|
||||
return array(
|
||||
array(Item::FLINT, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::FLINT, 0, 1],
|
||||
];
|
||||
}
|
||||
|
||||
return array(
|
||||
array(Item::GRAVEL, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::GRAVEL, 0, 1],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@ -31,25 +31,25 @@ class HayBale extends Solid{
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$faces = array(
|
||||
$faces = [
|
||||
0 => 0,
|
||||
1 => 0,
|
||||
2 => 0b1000,
|
||||
3 => 0b1000,
|
||||
4 => 0b0100,
|
||||
5 => 0b0100,
|
||||
);
|
||||
];
|
||||
|
||||
$this->meta = ($this->meta & 0x03) | $faces[$face];
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array($this->id, 0, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@ -30,7 +30,7 @@ class Ice extends Transparent{
|
||||
}
|
||||
|
||||
public function onBreak(Item $item){
|
||||
$this->getLevel()->setBlock($this, new Water(), true, false, true);
|
||||
$this->getLevel()->setBlock($this, new Water(), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -44,9 +44,9 @@ class Iron extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 3){
|
||||
return array(
|
||||
array(Item::IRON_BLOCK, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::IRON_BLOCK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -22,11 +22,9 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class IronBars extends Transparent{
|
||||
class IronBars extends Thin{
|
||||
public function __construct(){
|
||||
parent::__construct(self::IRON_BARS, 0, "Iron Bars");
|
||||
$this->isFullBlock = false;
|
||||
$this->isSolid = false;
|
||||
}
|
||||
|
||||
}
|
@ -49,9 +49,9 @@ class IronDoor extends Door{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::IRON_DOOR, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::IRON_DOOR, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -44,9 +44,9 @@ class IronOre extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 3){
|
||||
return array(
|
||||
array(Item::IRON_ORE, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::IRON_ORE, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ class JungleWoodStairs extends Stair{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array($this->id, 0, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -23,7 +23,9 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\entity\Entity;
|
||||
|
||||
class Ladder extends Transparent{
|
||||
public function __construct($meta = 0){
|
||||
@ -33,17 +35,66 @@ class Ladder extends Transparent{
|
||||
$this->hardness = 2;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
$entity->fallDistance = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
$f = 0.125;
|
||||
|
||||
if($this->meta === 2){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z + 1 - $f,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}elseif($this->meta === 3){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + $f
|
||||
);
|
||||
}elseif($this->meta === 4){
|
||||
return new AxisAlignedBB(
|
||||
$this->x + 1 - $f,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}elseif($this->meta === 5){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + $f,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
if($target->isTransparent === false){
|
||||
$faces = array(
|
||||
$faces = [
|
||||
2 => 2,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
5 => 5,
|
||||
);
|
||||
];
|
||||
if(isset($faces[$face])){
|
||||
$this->meta = $faces[$face];
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -65,8 +116,8 @@ class Ladder extends Transparent{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array($this->id, 0, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -44,9 +44,9 @@ class Lapis extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 3){
|
||||
return array(
|
||||
array(Item::LAPIS_BLOCK, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::LAPIS_BLOCK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -45,9 +45,9 @@ class LapisOre extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 3){
|
||||
return array(
|
||||
array(Item::DYE, 4, mt_rand(4, 8)),
|
||||
);
|
||||
return [
|
||||
[Item::DYE, 4, mt_rand(4, 8)],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -22,10 +22,12 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
|
||||
class Lava extends Liquid{
|
||||
public function __construct($meta = 0){
|
||||
@ -33,8 +35,22 @@ class Lava extends Liquid{
|
||||
$this->hardness = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
$entity->setOnFire(15);
|
||||
$ev = new EntityDamageEvent($entity, EntityDamageEvent::CAUSE_LAVA, 4);
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
||||
if(!$ev->isCancelled()){
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
$entity->attack(4, EntityDamageEvent::CAUSE_LAVA);
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$ret = $this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$ret = $this->getLevel()->setBlock($this, $this, true);
|
||||
$this->getLevel()->scheduleUpdate(clone $this, 40);
|
||||
|
||||
return $ret;
|
||||
|
@ -35,12 +35,12 @@ class Leaves extends Transparent{
|
||||
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::LEAVES, $meta, "Leaves");
|
||||
$names = array(
|
||||
$names = [
|
||||
self::OAK => "Oak Leaves",
|
||||
self::SPRUCE => "Spruce Leaves",
|
||||
self::BIRCH => "Birch Leaves",
|
||||
self::JUNGLE => "Jungle Leaves",
|
||||
);
|
||||
];
|
||||
$this->name = $names[$this->meta & 0x03];
|
||||
$this->hardness = 1;
|
||||
}
|
||||
@ -142,19 +142,19 @@ class Leaves extends Transparent{
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$this->meta |= 0x04;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
$drops = [];
|
||||
if($item->isShears()){
|
||||
$drops[] = array(Item::LEAVES, $this->meta & 0x03, 1);
|
||||
$drops[] = [Item::LEAVES, $this->meta & 0x03, 1];
|
||||
}else{
|
||||
if(mt_rand(1, 20) === 1){ //Saplings
|
||||
$drops[] = array(Item::SAPLING, $this->meta & 0x03, 1);
|
||||
$drops[] = [Item::SAPLING, $this->meta & 0x03, 1];
|
||||
}
|
||||
if(($this->meta & 0x03) === self::OAK and mt_rand(1, 200) === 1){ //Apples
|
||||
$drops[] = array(Item::APPLE, 0, 1);
|
||||
$drops[] = [Item::APPLE, 0, 1];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,10 +29,10 @@ class Leaves2 extends Leaves{
|
||||
|
||||
public function __construct($meta = 0){
|
||||
Transparent::__construct(self::LEAVES, $meta, "Leaves");
|
||||
$names = array(
|
||||
$names = [
|
||||
self::ACACIA => "Acacia Leaves",
|
||||
self::DARK_OAK => "Dark Oak Leaves",
|
||||
);
|
||||
];
|
||||
$this->name = $names[$this->meta & 0x03];
|
||||
$this->hardness = 1;
|
||||
}
|
||||
@ -131,16 +131,16 @@ class Leaves2 extends Leaves{
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$this->meta |= 0x04;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
$drops = [];
|
||||
if($item->isShears()){
|
||||
$drops[] = array(Item::LEAVES2, $this->meta & 0x03, 1);
|
||||
$drops[] = [Item::LEAVES2, $this->meta & 0x03, 1];
|
||||
}else{
|
||||
if(mt_rand(1, 20) === 1){ //Saplings
|
||||
$drops[] = array(Item::SAPLING, $this->meta & 0x03, 1);
|
||||
$drops[] = [Item::SAPLING, $this->meta & 0x03, 1];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,12 +23,18 @@ namespace pocketmine\block;
|
||||
|
||||
|
||||
class Liquid extends Transparent{
|
||||
public function __construct($id, $meta = 0, $name = "Unknown"){
|
||||
parent::__construct($id, $meta, $name);
|
||||
$this->isLiquid = true;
|
||||
$this->breakable = false;
|
||||
$this->isReplaceable = true;
|
||||
$this->isSolid = false;
|
||||
$this->isFullBlock = true;
|
||||
public $isLiquid = true;
|
||||
public $breakable = false;
|
||||
public $isReplaceable = true;
|
||||
public $isSolid = false;
|
||||
public $isFullBlock = true;
|
||||
|
||||
public function getFluidHeightPercent(){
|
||||
$d = $this->meta;
|
||||
if($d >= 8){
|
||||
$d = 0;
|
||||
}
|
||||
|
||||
return ($d + 1) / 9;
|
||||
}
|
||||
}
|
@ -31,14 +31,10 @@ class LitPumpkin extends Solid{
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$faces = array(
|
||||
0 => 4,
|
||||
1 => 2,
|
||||
2 => 5,
|
||||
3 => 3,
|
||||
);
|
||||
$this->meta = $faces[$player->getDirection()];
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
if($player instanceof Player){
|
||||
$this->meta = ((int) $player->getDirection() + 5) % 4;
|
||||
}
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ class Melon extends Transparent{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array(Item::MELON_SLICE, 0, mt_rand(3, 7)),
|
||||
);
|
||||
return [
|
||||
[Item::MELON_SLICE, 0, mt_rand(3, 7)],
|
||||
];
|
||||
}
|
||||
}
|
@ -32,10 +32,15 @@ class MelonStem extends Flowable{
|
||||
$this->hardness = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === self::FARMLAND){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -55,7 +60,7 @@ class MelonStem extends Flowable{
|
||||
if(mt_rand(0, 2) == 1){
|
||||
if($this->meta < 0x07){
|
||||
++$this->meta;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
|
||||
return Level::BLOCK_UPDATE_RANDOM;
|
||||
}else{
|
||||
@ -68,7 +73,7 @@ class MelonStem extends Flowable{
|
||||
$side = $this->getSide(mt_rand(2, 5));
|
||||
$d = $side->getSide(0);
|
||||
if($side->getID() === self::AIR and ($d->getID() === self::FARMLAND or $d->getID() === self::GRASS or $d->getID() === self::DIRT)){
|
||||
$this->getLevel()->setBlock($side, new Melon(), true, false, true);
|
||||
$this->getLevel()->setBlock($side, new Melon(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -82,7 +87,7 @@ class MelonStem extends Flowable{
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
$this->meta = 0x07;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
if(($player->gamemode & 0x01) === 0){
|
||||
$item->count--;
|
||||
}
|
||||
@ -94,8 +99,8 @@ class MelonStem extends Flowable{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array(Item::MELON_SEEDS, 0, mt_rand(0, 2)),
|
||||
);
|
||||
return [
|
||||
[Item::MELON_SEEDS, 0, mt_rand(0, 2)],
|
||||
];
|
||||
}
|
||||
}
|
@ -49,9 +49,9 @@ class MossStone extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::MOSS_STONE, $this->meta, 1),
|
||||
);
|
||||
return [
|
||||
[Item::MOSS_STONE, $this->meta, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* 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
|
||||
@ -22,6 +22,8 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\Position;
|
||||
|
||||
class Mycelium extends Solid{
|
||||
public function __construct(){
|
||||
@ -29,25 +31,25 @@ class Mycelium extends Solid{
|
||||
$this->hardness = 2.5;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return [
|
||||
[Item::DIRT, 0, 1],
|
||||
];
|
||||
}
|
||||
public function getDrops(Item $item){
|
||||
return [
|
||||
[Item::DIRT, 0, 1],
|
||||
];
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
if($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
//TODO: light levels
|
||||
$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 = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
|
||||
if($block->getSide(1) instanceof Transparent){
|
||||
$this->getLevel()->setBlock($block, new Mycelium());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public function onUpdate($type){
|
||||
if($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
//TODO: light levels
|
||||
$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()));
|
||||
if($block->getSide(1) instanceof Transparent){
|
||||
$this->getLevel()->setBlock($block, new Mycelium());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,9 +49,9 @@ class NetherBrick extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::NETHER_BRICKS, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::NETHER_BRICKS, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -49,9 +49,9 @@ class Netherrack extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::NETHERRACK, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::NETHERRACK, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -40,9 +40,9 @@ class Obsidian extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 5){
|
||||
return array(
|
||||
array(Item::OBSIDIAN, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::OBSIDIAN, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -32,14 +32,14 @@ class Planks extends Solid{
|
||||
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::PLANKS, $meta, "Wood Planks");
|
||||
$names = array(
|
||||
$names = [
|
||||
self::OAK => "Oak Wood Planks",
|
||||
self::SPRUCE => "Spruce Wood Planks",
|
||||
self::BIRCH => "Birch Wood Planks",
|
||||
self::JUNGLE => "Jungle Wood Planks",
|
||||
self::ACACIA => "Acacia Wood Planks",
|
||||
self::DARK_OAK => "Jungle Wood Planks",
|
||||
);
|
||||
];
|
||||
$this->name = $names[$this->meta & 0x07];
|
||||
$this->hardness = 15;
|
||||
}
|
||||
|
@ -21,8 +21,6 @@
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
||||
class Podzol extends Solid{
|
||||
public function __construct(){
|
||||
parent::__construct(self::PODZOL, 0, "Podzol");
|
||||
|
@ -32,10 +32,15 @@ class Potato extends Flowable{
|
||||
$this->hardness = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === self::FARMLAND){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -46,7 +51,7 @@ class Potato extends Flowable{
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
$this->meta = 0x07;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
if(($player->gamemode & 0x01) === 0){
|
||||
$item->count--;
|
||||
}
|
||||
@ -69,7 +74,7 @@ class Potato extends Flowable{
|
||||
if(mt_rand(0, 2) == 1){
|
||||
if($this->meta < 0x07){
|
||||
++$this->meta;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
|
||||
return Level::BLOCK_UPDATE_RANDOM;
|
||||
}
|
||||
@ -84,9 +89,9 @@ class Potato extends Flowable{
|
||||
public function getDrops(Item $item){
|
||||
$drops = [];
|
||||
if($this->meta >= 0x07){
|
||||
$drops[] = array(Item::POTATO, 0, mt_rand(1, 4));
|
||||
$drops[] = [Item::POTATO, 0, mt_rand(1, 4)];
|
||||
}else{
|
||||
$drops[] = array(Item::POTATO, 0, 1);
|
||||
$drops[] = [Item::POTATO, 0, 1];
|
||||
}
|
||||
|
||||
return $drops;
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Pumpkin extends Solid{
|
||||
public function __construct(){
|
||||
@ -28,4 +30,13 @@ class Pumpkin extends Solid{
|
||||
$this->hardness = 5;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
if($player instanceof Player){
|
||||
$this->meta = ((int) $player->getDirection() + 5) % 4;
|
||||
}
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -32,10 +32,15 @@ class PumpkinStem extends Flowable{
|
||||
$this->hardness = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === self::FARMLAND){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -56,7 +61,7 @@ class PumpkinStem extends Flowable{
|
||||
if(mt_rand(0, 2) == 1){
|
||||
if($this->meta < 0x07){
|
||||
++$this->meta;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
|
||||
return Level::BLOCK_UPDATE_RANDOM;
|
||||
}else{
|
||||
@ -69,7 +74,7 @@ class PumpkinStem extends Flowable{
|
||||
$side = $this->getSide(mt_rand(2, 5));
|
||||
$d = $side->getSide(0);
|
||||
if($side->getID() === self::AIR and ($d->getID() === self::FARMLAND or $d->getID() === self::GRASS or $d->getID() === self::DIRT)){
|
||||
$this->getLevel()->setBlock($side, new Pumpkin(), true, false, true);
|
||||
$this->getLevel()->setBlock($side, new Pumpkin(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,7 +88,7 @@ class PumpkinStem extends Flowable{
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
$this->meta = 0x07;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
if(($player->gamemode & 0x01) === 0){
|
||||
$item->count--;
|
||||
}
|
||||
@ -95,8 +100,8 @@ class PumpkinStem extends Flowable{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array(Item::PUMPKIN_SEEDS, 0, mt_rand(0, 2)),
|
||||
);
|
||||
return [
|
||||
[Item::PUMPKIN_SEEDS, 0, mt_rand(0, 2)],
|
||||
];
|
||||
}
|
||||
}
|
@ -26,12 +26,12 @@ use pocketmine\item\Item;
|
||||
class Quartz extends Solid{
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::QUARTZ_BLOCK, $meta, "Quartz Block");
|
||||
$names = array(
|
||||
$names = [
|
||||
0 => "Quartz Block",
|
||||
1 => "Chiseled Quartz Block",
|
||||
2 => "Quartz Pillar",
|
||||
3 => "Quartz Pillar",
|
||||
);
|
||||
];
|
||||
$this->name = $names[$this->meta & 0x03];
|
||||
}
|
||||
|
||||
@ -55,9 +55,9 @@ class Quartz extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::QUARTZ_BLOCK, $this->meta & 0x03, 1),
|
||||
);
|
||||
return [
|
||||
[Item::QUARTZ_BLOCK, $this->meta & 0x03, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -31,6 +31,11 @@ class RedMushroom extends Flowable{
|
||||
$this->hardness = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function onUpdate($type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->isTransparent === true){ //Replace with common break method
|
||||
@ -48,7 +53,7 @@ class RedMushroom extends Flowable{
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->isTransparent === false){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -42,9 +42,9 @@ class RedstoneOre extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 2){
|
||||
return array(
|
||||
array(Item::REDSTONE_DUST, 0, mt_rand(4, 5)),
|
||||
);
|
||||
return [
|
||||
[Item::REDSTONE_DUST, 0, mt_rand(4, 5)],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -26,11 +26,11 @@ use pocketmine\item\Item;
|
||||
class Sandstone extends Solid{
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::SANDSTONE, $meta, "Sandstone");
|
||||
$names = array(
|
||||
$names = [
|
||||
0 => "Sandstone",
|
||||
1 => "Chiseled Sandstone",
|
||||
2 => "Smooth Sandstone",
|
||||
);
|
||||
];
|
||||
$this->name = $names[$this->meta & 0x03];
|
||||
$this->hardness = 4;
|
||||
}
|
||||
@ -55,9 +55,9 @@ class Sandstone extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::SANDSTONE, $this->meta & 0x03, 1),
|
||||
);
|
||||
return [
|
||||
[Item::SANDSTONE, $this->meta & 0x03, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -37,22 +37,27 @@ class Sapling extends Flowable{
|
||||
public function __construct($meta = Sapling::OAK){
|
||||
parent::__construct(self::SAPLING, $meta, "Sapling");
|
||||
$this->isActivable = true;
|
||||
$names = array(
|
||||
$names = [
|
||||
0 => "Oak Sapling",
|
||||
1 => "Spruce Sapling",
|
||||
2 => "Birch Sapling",
|
||||
3 => "Jungle Sapling",
|
||||
4 => "Acacia Sapling",
|
||||
5 => "Dark Oak Sapling",
|
||||
);
|
||||
];
|
||||
$this->name = $names[$this->meta & 0x07];
|
||||
$this->hardness = 0;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === self::GRASS or $down->getID() === self::DIRT or $down->getID() === self::FARMLAND){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -89,7 +94,7 @@ class Sapling extends Flowable{
|
||||
Tree::growTree($this->getLevel(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->meta & 0x07);
|
||||
}else{
|
||||
$this->meta |= 0x08;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
|
||||
return Level::BLOCK_UPDATE_RANDOM;
|
||||
}
|
||||
@ -102,8 +107,8 @@ class Sapling extends Flowable{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array($this->id, $this->meta & 0x07, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, $this->meta & 0x07, 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -33,22 +33,27 @@ class SignPost extends Transparent{
|
||||
$this->hardness = 5;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
if($face !== 0){
|
||||
$faces = array(
|
||||
$faces = [
|
||||
2 => 2,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
5 => 5,
|
||||
);
|
||||
];
|
||||
if(!isset($faces[$face])){
|
||||
$this->meta = floor((($player->yaw + 180) * 16 / 360) + 0.5) & 0x0F;
|
||||
$this->getLevel()->setBlock($block, Block::get(Item::SIGN_POST, $this->meta), true, false, true);
|
||||
$this->getLevel()->setBlock($block, Block::get(Item::SIGN_POST, $this->meta), true);
|
||||
|
||||
return true;
|
||||
}else{
|
||||
$this->meta = $faces[$face];
|
||||
$this->getLevel()->setBlock($block, Block::get(Item::WALL_SIGN, $this->meta), true, false, true);
|
||||
$this->getLevel()->setBlock($block, Block::get(Item::WALL_SIGN, $this->meta), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -78,8 +83,8 @@ class SignPost extends Transparent{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array(Item::SIGN, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::SIGN, 0, 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -22,12 +22,13 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Slab extends Transparent{
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::SLAB, $meta, "Slab");
|
||||
$names = array(
|
||||
$names = [
|
||||
0 => "Stone",
|
||||
1 => "Sandstone",
|
||||
2 => "Wooden",
|
||||
@ -36,7 +37,7 @@ class Slab extends Transparent{
|
||||
5 => "Stone Brick",
|
||||
6 => "Quartz",
|
||||
7 => "",
|
||||
);
|
||||
];
|
||||
$this->name = (($this->meta & 0x08) === 0x08 ? "Upper " : "") . $names[$this->meta & 0x07] . " Slab";
|
||||
if(($this->meta & 0x08) === 0x08){
|
||||
$this->isFullBlock = true;
|
||||
@ -46,15 +47,37 @@ class Slab extends Transparent{
|
||||
$this->hardness = 30;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
if(($this->meta & 0x08) > 0){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y + 0.5,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 0.5,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$this->meta &= 0x07;
|
||||
if($face === 0){
|
||||
if($target->getID() === self::SLAB and ($target->getDamage() & 0x08) === 0x08 and ($target->getDamage() & 0x07) === ($this->meta & 0x07)){
|
||||
$this->getLevel()->setBlock($target, Block::get(Item::DOUBLE_SLAB, $this->meta), true, false, true);
|
||||
$this->getLevel()->setBlock($target, Block::get(Item::DOUBLE_SLAB, $this->meta), true);
|
||||
|
||||
return true;
|
||||
}elseif($block->getID() === self::SLAB and ($block->getDamage() & 0x07) === ($this->meta & 0x07)){
|
||||
$this->getLevel()->setBlock($block, Block::get(Item::DOUBLE_SLAB, $this->meta), true, false, true);
|
||||
$this->getLevel()->setBlock($block, Block::get(Item::DOUBLE_SLAB, $this->meta), true);
|
||||
|
||||
return true;
|
||||
}else{
|
||||
@ -62,11 +85,11 @@ class Slab extends Transparent{
|
||||
}
|
||||
}elseif($face === 1){
|
||||
if($target->getID() === self::SLAB and ($target->getDamage() & 0x08) === 0 and ($target->getDamage() & 0x07) === ($this->meta & 0x07)){
|
||||
$this->getLevel()->setBlock($target, Block::get(Item::DOUBLE_SLAB, $this->meta), true, false, true);
|
||||
$this->getLevel()->setBlock($target, Block::get(Item::DOUBLE_SLAB, $this->meta), true);
|
||||
|
||||
return true;
|
||||
}elseif($block->getID() === self::SLAB and ($block->getDamage() & 0x07) === ($this->meta & 0x07)){
|
||||
$this->getLevel()->setBlock($block, Block::get(Item::DOUBLE_SLAB, $this->meta), true, false, true);
|
||||
$this->getLevel()->setBlock($block, Block::get(Item::DOUBLE_SLAB, $this->meta), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -74,7 +97,7 @@ class Slab extends Transparent{
|
||||
}elseif(!($player instanceof Player)){
|
||||
if($block->getID() === self::SLAB){
|
||||
if(($block->getDamage() & 0x07) === ($this->meta & 0x07)){
|
||||
$this->getLevel()->setBlock($block, Block::get(Item::DOUBLE_SLAB, $this->meta), true, false, true);
|
||||
$this->getLevel()->setBlock($block, Block::get(Item::DOUBLE_SLAB, $this->meta), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -91,7 +114,7 @@ class Slab extends Transparent{
|
||||
if($block->getID() === self::SLAB and ($target->getDamage() & 0x07) !== ($this->meta & 0x07)){
|
||||
return false;
|
||||
}
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -116,9 +139,9 @@ class Slab extends Transparent{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array($this->id, $this->meta & 0x07, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, $this->meta & 0x07, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -34,10 +34,15 @@ class SnowLayer extends Flowable{
|
||||
$this->hardness = 0.5;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down instanceof Solid){
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -48,7 +53,7 @@ class SnowLayer extends Flowable{
|
||||
public function onUpdate($type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->getID() === self::AIR){ //Replace with common break method
|
||||
$this->getLevel()->setBlock($this, new Air(), true, false, true);
|
||||
$this->getLevel()->setBlock($this, new Air(), true);
|
||||
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
@ -59,9 +64,9 @@ class SnowLayer extends Flowable{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isShovel() !== false){
|
||||
return array(
|
||||
array(Item::SNOWBALL, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::SNOWBALL, 0, 1],
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
|
@ -22,10 +22,23 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
class SoulSand extends Solid{
|
||||
public function __construct(){
|
||||
parent::__construct(self::SOUL_SAND, 0, "Soul Sand");
|
||||
$this->hardness = 2.5;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1 - 0.125,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -29,8 +29,8 @@ class SpruceWoodStairs extends Stair{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array($this->id, 0, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ use pocketmine\item\Item;
|
||||
class StainedClay extends Solid{
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::STAINED_CLAY, $meta, "Stained Clay");
|
||||
$names = array(
|
||||
$names = [
|
||||
0 => "White Stained Clay",
|
||||
1 => "Orange Stained Clay",
|
||||
2 => "Magenta Stained Clay",
|
||||
@ -43,7 +43,7 @@ class StainedClay extends Solid{
|
||||
13 => "Green Stained Clay",
|
||||
14 => "Red Stained Clay",
|
||||
15 => "Black Stained Clay",
|
||||
);
|
||||
];
|
||||
$this->name = $names[$this->meta];
|
||||
$this->hardness = 30;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Stair extends Transparent{
|
||||
@ -36,27 +37,125 @@ class Stair extends Transparent{
|
||||
$this->hardness = 30;
|
||||
}
|
||||
|
||||
/*
|
||||
public function collidesWithBB(AxisAlignedBB $bb, &$list = []){
|
||||
$damage = $this->getDamage();
|
||||
$j = $damage & 0x03;
|
||||
|
||||
$f = 0;
|
||||
$f1 = 0.5;
|
||||
$f2 = 0.5;
|
||||
$f3 = 1;
|
||||
|
||||
if(($damage & 0x04) > 0){
|
||||
$f = 0.5;
|
||||
$f1 = 1;
|
||||
$f2 = 0;
|
||||
$f3 = 0.5;
|
||||
}
|
||||
|
||||
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y + $f,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + $f1,
|
||||
$this->z + 1
|
||||
))){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
|
||||
if($j === 0){
|
||||
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
|
||||
$this->x + 0.5,
|
||||
$this->y + $f2,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + $f3,
|
||||
$this->z + 1
|
||||
))){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}elseif($j === 1){
|
||||
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y + $f2,
|
||||
$this->z,
|
||||
$this->x + 0.5,
|
||||
$this->y + $f3,
|
||||
$this->z + 1
|
||||
))){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}elseif($j === 2){
|
||||
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y + $f2,
|
||||
$this->z + 0.5,
|
||||
$this->x + 1,
|
||||
$this->y + $f3,
|
||||
$this->z + 1
|
||||
))){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}elseif($j === 3){
|
||||
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y + $f2,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + $f3,
|
||||
$this->z + 0.5
|
||||
))){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
public function getBoundingBox(){
|
||||
if(($this->getDamage() & 0x04) > 0){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y + 0.5,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
}else{
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
$this->x + 1,
|
||||
$this->y + 0.5,
|
||||
$this->z + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$faces = array(
|
||||
$faces = [
|
||||
0 => 0,
|
||||
1 => 2,
|
||||
2 => 1,
|
||||
3 => 3,
|
||||
);
|
||||
];
|
||||
$this->meta = $faces[$player->getDirection()] & 0x03;
|
||||
if(($fy > 0.5 and $face !== 1) or $face === 0){
|
||||
$this->meta |= 0x04; //Upside-down stairs
|
||||
}
|
||||
$this->getLevel()->setBlock($block, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array($this->id, 0, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -21,6 +21,9 @@
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\entity\Entity;
|
||||
|
||||
class StillLava extends Liquid{
|
||||
public function __construct($meta = 0){
|
||||
@ -28,4 +31,18 @@ class StillLava extends Liquid{
|
||||
$this->hardness = 500;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
$entity->setOnFire(15);
|
||||
$ev = new EntityDamageEvent($entity, EntityDamageEvent::CAUSE_LAVA, 4);
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
||||
if(!$ev->isCancelled()){
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
$entity->attack(4, EntityDamageEvent::CAUSE_LAVA);
|
||||
}
|
||||
|
||||
}
|
@ -21,7 +21,6 @@
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class StillWater extends Water{
|
||||
public function __construct($meta = 0){
|
||||
Liquid::__construct(self::STILL_WATER, $meta, "Still Water");
|
||||
|
@ -32,8 +32,11 @@ class Stone extends Solid{
|
||||
const ANDESITE = 5;
|
||||
const POLISHED_ANDESITE = 6;
|
||||
|
||||
protected $hardness = 30;
|
||||
protected $id = self::STONE;
|
||||
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::STONE, $meta, "Stone");
|
||||
$this->meta = $meta;
|
||||
$names = [
|
||||
self::NORMAL => "Stone",
|
||||
self::GRANITE => "Granite",
|
||||
@ -44,7 +47,6 @@ class Stone extends Solid{
|
||||
self::POLISHED_ANDESITE => "Polished Andesite",
|
||||
];
|
||||
$this->name = $names[$this->meta & 0x07];
|
||||
$this->hardness = 30;
|
||||
}
|
||||
|
||||
public function getBreakTime(Item $item){
|
||||
@ -66,9 +68,9 @@ class Stone extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::COBBLESTONE, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::COBBLESTONE, 0, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
@ -26,12 +26,12 @@ use pocketmine\item\Item;
|
||||
class StoneBricks extends Solid{
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::STONE_BRICKS, $meta, "Stone Bricks");
|
||||
$names = array(
|
||||
$names = [
|
||||
0 => "Stone Bricks",
|
||||
1 => "Mossy Stone Bricks",
|
||||
2 => "Cracked Stone Bricks",
|
||||
3 => "Chiseled Stone Bricks",
|
||||
);
|
||||
];
|
||||
$this->name = $names[$this->meta & 0x03];
|
||||
$this->hardness = 30;
|
||||
}
|
||||
@ -56,9 +56,9 @@ class StoneBricks extends Solid{
|
||||
|
||||
public function getDrops(Item $item){
|
||||
if($item->isPickaxe() >= 1){
|
||||
return array(
|
||||
array(Item::STONE_BRICKS, $this->meta & 0x03, 1),
|
||||
);
|
||||
return [
|
||||
[Item::STONE_BRICKS, $this->meta & 0x03, 1],
|
||||
];
|
||||
}else{
|
||||
return [];
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user