mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-10 19:48:13 +00:00
Compare commits
262 Commits
Alpha_1.4d
...
Alpha_1.4d
Author | SHA1 | Date | |
---|---|---|---|
b6025e3f2b | |||
35de331b74 | |||
de11cce154 | |||
d53ba52d32 | |||
9db2fe40eb | |||
57bb8f14fa | |||
761cd59514 | |||
4c2a1c8684 | |||
31bb6d1a68 | |||
cd65179aef | |||
9abd2c63f4 | |||
376e359577 | |||
571e2f8895 | |||
7106ea87e6 | |||
6b65b68ebc | |||
d4c75ce68a | |||
fae330d499 | |||
5e03e157ad | |||
b0c40dc1ab | |||
6840589f4e | |||
19e4aaa16a | |||
e0a7944faa | |||
eeda22d0ba | |||
769f1effb0 | |||
42c7322273 | |||
c8cf6b715e | |||
41f94f7385 | |||
602bdf27a5 | |||
539fa232f8 | |||
f8378c09ba | |||
69fb7ae525 | |||
ee8ad6f92a | |||
f888acbd7c | |||
215691f1c4 | |||
1252dd65a9 | |||
762c27affe | |||
706e1099a1 | |||
9cd66dc969 | |||
5b6b789ab3 | |||
85ff696ae5 | |||
25f8e8318b | |||
61d84c73d0 | |||
f5822c6de8 | |||
b0bd927545 | |||
fde61b7d21 | |||
886ad8442c | |||
7b5869bea8 | |||
3063863c65 | |||
0dfaa19380 | |||
7fea29e874 | |||
2ded2013bf | |||
aa27c28e65 | |||
05a81bebf4 | |||
ce91f2943a | |||
1d8562fb8c | |||
1dfb17b932 | |||
16384c2b20 | |||
48041b2f19 | |||
529bf743db | |||
48bc919a33 | |||
474091c013 | |||
666e5553c2 | |||
ae6f532b1d | |||
b231eba803 | |||
82d903733d | |||
8e2903da86 | |||
d720113ac9 | |||
5db45222c6 | |||
2975509d0f | |||
7e49d073fa | |||
ef3674a296 | |||
6cb7e36f8a | |||
b88f19bb74 | |||
8c3fcf0798 | |||
6b312a7826 | |||
9907e84eee | |||
01f299a7f1 | |||
91f20f6789 | |||
4c1edc3f7e | |||
5fd1e271c5 | |||
593b0497b0 | |||
0907aedcef | |||
0a29e66b62 | |||
3cc4afbcd6 | |||
b3ae6eae04 | |||
3b56b536b6 | |||
9258281546 | |||
e7897be7cd | |||
5ff01de413 | |||
f191ada405 | |||
addd74d09e | |||
4e9d2d0a7f | |||
d04e994d1b | |||
3d870629f2 | |||
8dbe834dc3 | |||
36d8100e17 | |||
b880bf13f8 | |||
1ac08ce404 | |||
689b2ea877 | |||
d1f22ee395 | |||
056ed4802f | |||
bcb65e9a48 | |||
5404ba77d0 | |||
ae54426836 | |||
ee7d84dfbd | |||
3e1ea23036 | |||
d312d2a143 | |||
8c627bd0af | |||
6fb7170556 | |||
50f5c6d8ed | |||
f9d5c5bd37 | |||
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 |
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.10
|
||||
- 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
|
@ -72,6 +72,19 @@ class ExampleClass{
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### RFC and Voting
|
||||
* These are big Pull Requests or contributions that change important behavior.
|
||||
* RFCs will be tagged with the *PR: RFC* label
|
||||
* A vote will be held once the RFC is ready. All users can vote commenting on the Pull Request
|
||||
* Comments MUST use "Yes" or "No" on the FIRST sentence to signify the vote, except when they don't want it to be counted.
|
||||
* If your comment is a voting comment, specify the reason of your vote or it won't be counted.
|
||||
* After voting has been closed, no further votes will be counted.
|
||||
* An RFC will be rejected if less than 50% + 1 (simple majority) has voted Yes.
|
||||
* If the RFC is approved, Team Members have the final word on its implementation or rejection.
|
||||
* RFCs with complex voting options will specify the vote percentage or other details.
|
||||
|
||||
|
||||
## Bug Tracking for Collaborators
|
||||
|
||||
### Labels
|
||||
@ -91,6 +104,7 @@ Category labels are prefixed by `C:`. Multiple category labels may be applied to
|
||||
Pull Requests are prefixed by `PR:`. Only one label may be applied for a Pull Request.
|
||||
- PR: Bug Fix - This label is applied when the Pull Request fixes a bug.
|
||||
- PR: Contribution - This label is applied when the Pull Request contributes code to PocketMine-MP such as a new feature or an improvement.
|
||||
- PR: RFC - Request for Comments
|
||||
|
||||
#### Status
|
||||
Status labels show the status of the issue. Multiple status labels may be applied.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\network\protocol\Info;
|
||||
use pocketmine\plugin\PluginBase;
|
||||
use pocketmine\plugin\PluginLoadOrder;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
@ -137,7 +138,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 +154,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"];
|
||||
@ -179,7 +180,7 @@ class CrashDump{
|
||||
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
|
||||
$this->data["plugin"] = true;
|
||||
|
||||
$reflection = new \ReflectionClass("pocketmine\\plugin\\PluginBase");
|
||||
$reflection = new \ReflectionClass(PluginBase::class);
|
||||
$file = $reflection->getProperty("file");
|
||||
$file->setAccessible(true);
|
||||
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
|
||||
@ -228,7 +229,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());
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -73,10 +73,17 @@ namespace pocketmine {
|
||||
use raklib\RakLib;
|
||||
|
||||
const VERSION = "Alpha_1.4dev";
|
||||
const API_VERSION = "1.3.1";
|
||||
const API_VERSION = "1.4.1";
|
||||
const CODENAME = "絶好(Zekkou)ケーキ(Cake)";
|
||||
const MINECRAFT_VERSION = "v0.9.5 alpha";
|
||||
|
||||
/*
|
||||
* Startup code. Do not look at it, it may harm you.
|
||||
* Most of them are hacks to fix date-related bugs, or basic functions used after this
|
||||
* This is the only non-class based file on this project.
|
||||
* Enjoy it as much as I did writing it. I don't want to do it again.
|
||||
*/
|
||||
|
||||
if(\Phar::running(true) !== ""){
|
||||
@define("pocketmine\\PATH", \Phar::running(true) . "/");
|
||||
}else{
|
||||
@ -98,46 +105,12 @@ namespace pocketmine {
|
||||
$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
|
||||
|
||||
set_time_limit(0); //Who set it to 30 seconds?!?!
|
||||
|
||||
if(ini_get("date.timezone") == ""){ //No Timezone set
|
||||
date_default_timezone_set("GMT");
|
||||
if(strpos(" " . strtoupper(php_uname("s")), " WIN") !== false){
|
||||
$time = time();
|
||||
$time -= $time % 60;
|
||||
//TODO: Parse different time & date formats by region. ¬¬ world
|
||||
//Example: USA
|
||||
@exec("time.exe /T", $hour);
|
||||
$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;
|
||||
}else{
|
||||
@exec("date +%s", $t);
|
||||
$offset = @round((intval(trim($t[0])) - time()) / 60) * 60;
|
||||
}
|
||||
|
||||
$daylight = (int) date("I");
|
||||
$d = timezone_name_from_abbr("", $offset, $daylight);
|
||||
@ini_set("date.timezone", $d);
|
||||
date_default_timezone_set($d);
|
||||
}else{
|
||||
$d = @date_default_timezone_get();
|
||||
if(strpos($d, "/") === false){
|
||||
$d = timezone_name_from_abbr($d);
|
||||
@ini_set("date.timezone", $d);
|
||||
date_default_timezone_set($d);
|
||||
}
|
||||
}
|
||||
|
||||
gc_enable();
|
||||
error_reporting(-1);
|
||||
ini_set("allow_url_fopen", 1);
|
||||
@ -148,15 +121,158 @@ 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", "enable-profiler"));
|
||||
$opts = getopt("", ["enable-ansi", "disable-ansi", "data:", "plugins:", "no-wizard", "enable-profiler"]);
|
||||
|
||||
define("pocketmine\\DATA", isset($opts["data"]) ? realpath($opts["data"]) . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR);
|
||||
define("pocketmine\\PLUGIN_PATH", isset($opts["plugins"]) ? realpath($opts["plugins"]) . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
|
||||
|
||||
define("pocketmine\\ANSI", ((strpos(strtoupper(php_uname("s")), "WIN") === false or isset($opts["enable-ansi"])) and !isset($opts["disable-ansi"])));
|
||||
|
||||
//Logger has a dependency on timezone, so we'll set it to UTC until we can get the actual timezone.
|
||||
date_default_timezone_set("UTC");
|
||||
$logger = new MainLogger(\pocketmine\DATA . "server.log", \pocketmine\ANSI);
|
||||
|
||||
if(!ini_get("date.timezone")){
|
||||
if(($timezone = detect_system_timezone()) and date_default_timezone_set($timezone)){
|
||||
//Success! Timezone has already been set and validated in the if statement.
|
||||
//This here is just for redundancy just in case some stupid program wants to read timezone data from the ini.
|
||||
ini_set("date.timezone", $timezone);
|
||||
}else{
|
||||
//If system timezone detection fails or timezone is an invalid value.
|
||||
if($response = Utils::getURL("http://ip-api.com/json")
|
||||
and $ip_geolocation_data = json_decode($response, true)
|
||||
and $ip_geolocation_data['status'] != 'fail'
|
||||
and date_default_timezone_set($ip_geolocation_data['timezone']))
|
||||
{
|
||||
//Again, for redundancy.
|
||||
ini_set("date.timezone", $ip_geolocation_data['timezone']);
|
||||
}else{
|
||||
ini_set("date.timezone", "UTC");
|
||||
date_default_timezone_set("UTC");
|
||||
$logger->warning("Timezone could not be automatically determined. An incorrect timezone will result in incorrect timestamps on console logs. It has been set to \"UTC\" by default. You can change it on the php.ini file.");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/*
|
||||
* This is here so that stupid idiots don't come to us complaining and fill up the issue tracker when they put an incorrect timezone abbreviation in php.ini apparently.
|
||||
*/
|
||||
$default_timezone = date_default_timezone_get();
|
||||
if(strpos($default_timezone, "/") === false){
|
||||
$default_timezone = timezone_name_from_abbr($default_timezone);
|
||||
ini_set("date.timezone", $default_timezone);
|
||||
date_default_timezone_set($default_timezone);
|
||||
}
|
||||
}
|
||||
|
||||
function detect_system_timezone(){
|
||||
switch(Utils::getOS()){
|
||||
case 'win':
|
||||
$regex = '/(?:Time Zone:\s*\()(UTC)(\+*\-*\d*\d*\:*\d*\d*)(?:\))/';
|
||||
|
||||
exec("systeminfo", $output);
|
||||
|
||||
$string = trim(implode("\n", $output));
|
||||
|
||||
//Detect the Time Zone string in systeminfo
|
||||
preg_match($regex, $string, $matches);
|
||||
|
||||
if(!isset($matches[2]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$offset = $matches[2];
|
||||
|
||||
if($offset == ""){
|
||||
return "UTC";
|
||||
}
|
||||
|
||||
return parse_offset($offset);
|
||||
break;
|
||||
case 'linux':
|
||||
// Ubuntu / Debian.
|
||||
if(file_exists('/etc/timezone')){
|
||||
$data = file_get_contents('/etc/timezone');
|
||||
if($data){
|
||||
return trim($data);
|
||||
}
|
||||
}
|
||||
|
||||
// RHEL / CentOS
|
||||
if(file_exists('/etc/sysconfig/clock')){
|
||||
$data = parse_ini_file('/etc/sysconfig/clock');
|
||||
if(!empty($data['ZONE'])){
|
||||
return trim($data['ZONE']);
|
||||
}
|
||||
}
|
||||
|
||||
//Portable method for incompatible linux distributions.
|
||||
|
||||
$offset = trim(exec('date +%:z'));
|
||||
|
||||
if($offset == "+00:00"){
|
||||
return "UTC";
|
||||
}
|
||||
|
||||
return parse_offset($offset);
|
||||
break;
|
||||
case 'mac':
|
||||
if(is_link('/etc/localtime')){
|
||||
$filename = readlink('/etc/localtime');
|
||||
if(strpos($filename, '/usr/share/zoneinfo/') === 0){
|
||||
$timezone = substr($filename, 20);
|
||||
return trim($timezone);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $offset In the format of +09:00, +02:00, -04:00 etc.
|
||||
* @return string
|
||||
*/
|
||||
function parse_offset($offset){
|
||||
//Make signed offsets unsigned for date_parse
|
||||
if(strpos($offset, '-') !== false){
|
||||
$negative_offset = true;
|
||||
$offset = str_replace('-', '', $offset);
|
||||
}else{
|
||||
if(strpos($offset, '+') !== false){
|
||||
$negative_offset = false;
|
||||
$offset = str_replace('+', '', $offset);
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$parsed = date_parse($offset);
|
||||
$offset = $parsed['hour'] * 3600 + $parsed['minute'] * 60 + $parsed['second'];
|
||||
|
||||
//After date_parse is done, put the sign back
|
||||
if($negative_offset == true){
|
||||
$offset = -abs($offset);
|
||||
}
|
||||
|
||||
//And then, look the offset up.
|
||||
//timezone_name_from_abbr is not used because it returns false on some(most) offsets because it's mapping function is weird.
|
||||
//That's been a bug in PHP since 2008!
|
||||
foreach(timezone_abbreviations_list() as $zones){
|
||||
foreach($zones as $timezone){
|
||||
if($timezone['offset'] == $offset){
|
||||
return $timezone['timezone_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(isset($opts["enable-profiler"])){
|
||||
if(function_exists("profiler_enable")){
|
||||
\profiler_enable();
|
||||
@ -217,7 +333,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",
|
||||
@ -233,7 +349,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){
|
||||
@ -263,8 +379,8 @@ namespace pocketmine {
|
||||
|
||||
$errors = 0;
|
||||
|
||||
if(version_compare("5.5.0", PHP_VERSION) > 0){
|
||||
$logger->critical("Use PHP >= 5.5.0");
|
||||
if(version_compare("5.6.0", PHP_VERSION) > 0){
|
||||
$logger->critical("You must use PHP >= 5.6");
|
||||
++$errors;
|
||||
}
|
||||
|
||||
@ -282,8 +398,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;
|
||||
}
|
||||
|
||||
|
@ -42,9 +42,14 @@ use pocketmine\inventory\CraftingManager;
|
||||
use pocketmine\inventory\InventoryType;
|
||||
use pocketmine\inventory\Recipe;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\format\anvil\Anvil;
|
||||
use pocketmine\level\format\LevelProviderManager;
|
||||
use pocketmine\level\format\mcregion\McRegion;
|
||||
use pocketmine\level\generator\Flat;
|
||||
use pocketmine\level\generator\GenerationInstanceManager;
|
||||
use pocketmine\level\generator\GenerationRequestManager;
|
||||
use pocketmine\level\generator\Generator;
|
||||
use pocketmine\level\generator\Normal;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\metadata\EntityMetadataStore;
|
||||
use pocketmine\metadata\LevelMetadataStore;
|
||||
@ -61,7 +66,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;
|
||||
@ -78,6 +82,7 @@ use pocketmine\scheduler\ServerScheduler;
|
||||
use pocketmine\tile\Tile;
|
||||
use pocketmine\updater\AutoUpdater;
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\Cache;
|
||||
use pocketmine\utils\Config;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use pocketmine\utils\TextFormat;
|
||||
@ -128,15 +133,15 @@ 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;
|
||||
|
||||
/** @var CommandReader */
|
||||
private $console = null;
|
||||
private $consoleThreaded;
|
||||
|
||||
/** @var SimpleCommandMap */
|
||||
private $commandMap = null;
|
||||
@ -150,6 +155,9 @@ class Server{
|
||||
/** @var int */
|
||||
private $maxPlayers;
|
||||
|
||||
/** @var bool */
|
||||
private $autoSave;
|
||||
|
||||
/** @var RCON */
|
||||
private $rcon;
|
||||
|
||||
@ -292,6 +300,23 @@ class Server{
|
||||
return $this->getConfigString("server-name", "Unknown server");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getAutoSave(){
|
||||
return $this->autoSave;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $value
|
||||
*/
|
||||
public function setAutoSave($value){
|
||||
$this->autoSave = (bool) $value;
|
||||
foreach($this->getLevels() as $level){
|
||||
$level->setAutoSave($this->autoSave);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
@ -537,7 +562,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 +660,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 +677,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 +712,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 +822,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 +836,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -876,7 +915,7 @@ class Server{
|
||||
* @return bool
|
||||
*/
|
||||
public function unloadLevel(Level $level, $forceUnload = false){
|
||||
if($level->unload($forceUnload) === true and $this->isLevelLoaded($level->getFolderName())){
|
||||
if($level->unload($forceUnload) === true){
|
||||
unset($this->levels[$level->getID()]);
|
||||
|
||||
return true;
|
||||
@ -930,6 +969,8 @@ class Server{
|
||||
|
||||
$this->levels[$level->getID()] = $level;
|
||||
|
||||
$level->initLevel();
|
||||
|
||||
$this->getPluginManager()->callEvent(new LevelLoadEvent($level));
|
||||
|
||||
/*foreach($entities->getAll() as $entity){
|
||||
@ -1045,15 +1086,11 @@ class Server{
|
||||
|
||||
$seed = $seed === null ? Binary::readInt(Utils::getRandomBytes(4, false)) : (int) $seed;
|
||||
|
||||
if($generator !== null and class_exists($generator) and is_subclass_of($generator, "pocketmine\\level\\generator\\Generator")){
|
||||
if($generator !== null and class_exists($generator) and is_subclass_of($generator, Generator::class)){
|
||||
$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){
|
||||
@ -1067,6 +1104,8 @@ class Server{
|
||||
$level = new Level($this, $name, $path, $provider);
|
||||
$this->levels[$level->getID()] = $level;
|
||||
|
||||
$level->initLevel();
|
||||
|
||||
$this->getPluginManager()->callEvent(new LevelInitEvent($level));
|
||||
|
||||
$this->getPluginManager()->callEvent(new LevelLoadEvent($level));
|
||||
@ -1084,7 +1123,7 @@ class Server{
|
||||
|
||||
for($X = -$radius; $X <= $radius; ++$X){
|
||||
for($Z = -$radius; $Z <= $radius; ++$Z){
|
||||
$distance = ($X * $X) + ($Z * $Z);
|
||||
$distance = $X ** 2 + $Z ** 2;
|
||||
if($distance > $radiusSquared){
|
||||
continue;
|
||||
}
|
||||
@ -1142,7 +1181,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 +1231,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 +1254,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{
|
||||
@ -1411,7 +1450,8 @@ class Server{
|
||||
$this->banByIP = new BanList($this->dataPath . "banned-ips.txt");
|
||||
$this->banByIP->load();
|
||||
|
||||
$this->console = new CommandReader();
|
||||
$this->consoleThreaded = new \Threaded();
|
||||
$this->console = new CommandReader($this->consoleThreaded);
|
||||
|
||||
$version = new VersionString($this->getPocketMineVersion());
|
||||
$this->logger->info("Starting Minecraft: PE server version " . TextFormat::AQUA . $this->getVersion());
|
||||
@ -1427,7 +1467,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 +1491,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);
|
||||
|
||||
@ -1462,9 +1502,10 @@ class Server{
|
||||
}
|
||||
|
||||
$this->maxPlayers = $this->getConfigInt("max-players", 20);
|
||||
$this->setAutoSave($this->getConfigBoolean("auto-save", true));
|
||||
|
||||
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 < 128){
|
||||
$this->logger->warning($this->getName() . " may not work right with less than 128MB of RAM", true, true, 0);
|
||||
@ -1487,9 +1528,9 @@ class Server{
|
||||
$this->logger->info("Advanced cache enabled");
|
||||
}
|
||||
|
||||
Level::$COMPRESSION_LEVEL = $this->getProperty("chunk-sending.compression-level", 7);
|
||||
Level::$COMPRESSION_LEVEL = $this->getProperty("chunk-sending.compression-level", 8);
|
||||
|
||||
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0 and function_exists("cli_set_process_title")){
|
||||
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0){
|
||||
@cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion());
|
||||
}
|
||||
|
||||
@ -1502,6 +1543,9 @@ class Server{
|
||||
$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,13 +1554,10 @@ 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));
|
||||
$this->pluginManager->registerInterface("pocketmine\\plugin\\PharPluginLoader");
|
||||
$this->pluginManager->registerInterface(PharPluginLoader::class);
|
||||
|
||||
set_exception_handler([$this, "exceptionHandler"]);
|
||||
register_shutdown_function([$this, "crashDump"]);
|
||||
@ -1528,15 +1569,26 @@ class Server{
|
||||
|
||||
$this->enablePlugins(PluginLoadOrder::STARTUP);
|
||||
|
||||
$this->generationManager = new GenerationRequestManager($this);
|
||||
if($this->getProperty("chunk-generation.use-async", true)){
|
||||
$this->generationManager = new GenerationRequestManager($this);
|
||||
}else{
|
||||
$this->generationManager = new GenerationInstanceManager($this);
|
||||
}
|
||||
|
||||
LevelProviderManager::addProvider($this, "pocketmine\\level\\format\\anvil\\Anvil");
|
||||
LevelProviderManager::addProvider($this, "pocketmine\\level\\format\\mcregion\\McRegion");
|
||||
LevelProviderManager::addProvider($this, Anvil::class);
|
||||
LevelProviderManager::addProvider($this, McRegion::class);
|
||||
|
||||
|
||||
Generator::addGenerator("pocketmine\\level\\generator\\Flat", "flat");
|
||||
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "normal");
|
||||
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "default");
|
||||
Generator::addGenerator(Flat::class, "flat");
|
||||
Generator::addGenerator(Normal::class, "normal");
|
||||
Generator::addGenerator(Normal::class, "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){
|
||||
@ -1558,7 +1610,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");
|
||||
}
|
||||
@ -1580,9 +1632,9 @@ class Server{
|
||||
return;
|
||||
}
|
||||
|
||||
$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([Cache::class, "cleanup"]), $this->getProperty("ticks-per.cache-cleanup", 900), $this->getProperty("ticks-per.cache-cleanup", 900));
|
||||
if($this->getAutoSave() and $this->getProperty("ticks-per.autosave", 6000) > 0){
|
||||
$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){
|
||||
@ -1596,11 +1648,17 @@ class Server{
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param Player[]|null $recipients
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function broadcastMessage($message){
|
||||
return $this->broadcast($message, self::BROADCAST_CHANNEL_USERS);
|
||||
public function broadcastMessage($message, $recipients = null){
|
||||
if(!is_array($recipients)){
|
||||
return $this->broadcast($message, self::BROADCAST_CHANNEL_USERS);
|
||||
}
|
||||
foreach($recipients as $recipient){
|
||||
$recipient->sendMessage($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1694,8 +1752,14 @@ class Server{
|
||||
* @param string $commandLine
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function dispatchCommand(CommandSender $sender, $commandLine){
|
||||
if(!($sender instanceof CommandSender)){
|
||||
throw new \Exception("CommandSender is not valid");
|
||||
}
|
||||
|
||||
if($this->commandMap->dispatch($sender, $commandLine)){
|
||||
return true;
|
||||
}
|
||||
@ -1725,7 +1789,7 @@ 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($this->getName() . " may not work right with less than 256MB of RAM", true, true, 0);
|
||||
@ -1745,7 +1809,7 @@ class Server{
|
||||
$this->operators->reload();
|
||||
|
||||
|
||||
$this->pluginManager->registerInterface("pocketmine\\plugin\\PharPluginLoader");
|
||||
$this->pluginManager->registerInterface(PharPluginLoader::class);
|
||||
$this->pluginManager->loadPlugins($this->pluginPath);
|
||||
$this->enablePlugins(PluginLoadOrder::STARTUP);
|
||||
$this->enablePlugins(PluginLoadOrder::POSTWORLD);
|
||||
@ -1809,7 +1873,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();
|
||||
}
|
||||
|
||||
@ -1828,7 +1892,10 @@ class Server{
|
||||
$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 "?"');
|
||||
|
||||
@ -1894,7 +1961,8 @@ class Server{
|
||||
}
|
||||
}elseif(\Phar::running(true) == ""){
|
||||
return;
|
||||
}elseif($dump->getData()["type"] === "E_PARSE" or $dump->getData()["type"] === "E_COMPILE_ERROR"){
|
||||
}
|
||||
if($dump->getData()["error"]["type"] === "E_PARSE" or $dump->getData()["error"]["type"] === "E_COMPILE_ERROR"){
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1917,31 +1985,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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1951,32 +2003,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);
|
||||
@ -1984,16 +2010,21 @@ class Server{
|
||||
}
|
||||
|
||||
public function doAutoSave(){
|
||||
if($this->getAutoSave()){
|
||||
Timings::$worldSaveTimer->startTiming();
|
||||
foreach($this->getOnlinePlayers() as $index => $player){
|
||||
if($player->isOnline()){
|
||||
$player->save();
|
||||
}elseif(!$player->isConnected()){
|
||||
unset($this->players[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
Timings::$worldSaveTimer->startTiming();
|
||||
foreach($this->getOnlinePlayers() as $player){
|
||||
$player->save();
|
||||
foreach($this->getLevels() as $level){
|
||||
$level->save(false);
|
||||
}
|
||||
Timings::$worldSaveTimer->stopTiming();
|
||||
}
|
||||
|
||||
foreach($this->getLevels() as $level){
|
||||
$level->save(false);
|
||||
}
|
||||
Timings::$worldSaveTimer->stopTiming();
|
||||
}
|
||||
|
||||
public function doLevelGC(){
|
||||
@ -2008,35 +2039,37 @@ 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(
|
||||
"serverid" => Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() . ":" . $this->getPort()), 0, 8)),
|
||||
$this->lastSendUsage = new SendUsageTask("http://stats.pocketmine.net/usage.php", [
|
||||
"serverid" => $this->serverID,
|
||||
"port" => $this->getPort(),
|
||||
"os" => Utils::getOS(),
|
||||
"name" => $this->getName(),
|
||||
"memory_total" => $this->getConfigString("memory-limit"),
|
||||
"memory_usage" => memory_get_usage(),
|
||||
"php_version" => PHP_VERSION,
|
||||
"version" => $version->get(false),
|
||||
"version" => $version->get(true),
|
||||
"build" => $version->getBuild(),
|
||||
"mc_version" => \pocketmine\MINECRAFT_VERSION,
|
||||
"protocol" => network\protocol\Info::CURRENT_PROTOCOL,
|
||||
"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;". $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() . "\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";
|
||||
}
|
||||
}
|
||||
|
||||
@ -2044,44 +2077,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->process();
|
||||
|
||||
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],
|
||||
];
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\network\protocol\ChatPacket;
|
||||
use pocketmine\Player;
|
||||
|
||||
@ -34,6 +35,17 @@ 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){
|
||||
|
||||
$time = $this->getLevel()->getTime() % Level::TIME_FULL;
|
||||
@ -86,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;
|
||||
}
|
||||
@ -115,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],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@ -39,7 +39,7 @@ class Beetroot extends Flowable{
|
||||
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;
|
||||
}
|
||||
@ -49,8 +49,11 @@ 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->meta += mt_rand(2, 5);
|
||||
if($this->meta > 7){
|
||||
$this->meta = 7;
|
||||
}
|
||||
$this->getLevel()->setBlock($this, $this, true, true);
|
||||
$item->count--;
|
||||
|
||||
return true;
|
||||
@ -63,7 +66,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;
|
||||
}
|
||||
@ -71,7 +74,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;
|
||||
}
|
||||
@ -86,10 +89,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,7 +503,7 @@ abstract class Block extends Position implements Metadatable{
|
||||
[Item::DYE, 9],
|
||||
[Item::DYE, 8],
|
||||
|
||||
);
|
||||
];
|
||||
|
||||
/** @var Block[] */
|
||||
public static $list = [];
|
||||
@ -526,7 +529,7 @@ abstract class Block extends Position implements Metadatable{
|
||||
|
||||
public static function init(){
|
||||
if(count(self::$list) === 0){
|
||||
self::$list = array(
|
||||
self::$list = [
|
||||
self::AIR => Air::class,
|
||||
self::STONE => Stone::class,
|
||||
self::GRASS => Grass::class,
|
||||
@ -663,7 +666,7 @@ abstract class Block extends Position implements Metadatable{
|
||||
self::STONECUTTER => Stonecutter::class,
|
||||
self::GLOWING_OBSIDIAN => GlowingObsidian::class,
|
||||
self::NETHER_REACTOR => NetherReactor::class,
|
||||
);
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -721,6 +724,10 @@ abstract class Block extends Position implements Metadatable{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function addVelocityToEntity(Entity $entity, Vector3 $vector){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
@ -759,7 +766,7 @@ abstract class Block extends Position implements Metadatable{
|
||||
return [];
|
||||
}else{
|
||||
return [
|
||||
array($this->id, $this->meta, 1),
|
||||
[$this->id, $this->meta, 1],
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -830,6 +837,13 @@ abstract class Block extends Position implements Metadatable{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
*/
|
||||
public function onEntityCollide(Entity $entity){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB
|
||||
*/
|
||||
@ -844,6 +858,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,7 +47,7 @@ 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;
|
||||
}
|
||||
|
@ -39,29 +39,29 @@ 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);
|
||||
new Furnace($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onBreak(Item $item){
|
||||
$this->getLevel()->setBlock($this, new Air(), true, true, true);
|
||||
$this->getLevel()->setBlock($this, new Air(), true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -73,15 +73,15 @@ 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);
|
||||
$furnace = new Furnace($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
}
|
||||
|
||||
if(($player->getGamemode() & 0x01) === 0x01){
|
||||
@ -114,16 +114,7 @@ class BurningFurnace extends Solid{
|
||||
public function getDrops(Item $item){
|
||||
$drops = [];
|
||||
if($item->isPickaxe() >= 1){
|
||||
$drops[] = array(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[] = [Item::FURNACE, 0, 1];
|
||||
}
|
||||
|
||||
return $drops;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class Carrot extends Flowable{
|
||||
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;
|
||||
}
|
||||
@ -50,8 +50,11 @@ 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->meta += mt_rand(2, 5);
|
||||
if($this->meta > 7){
|
||||
$this->meta = 7;
|
||||
}
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
$item->count--;
|
||||
|
||||
return true;
|
||||
@ -73,7 +76,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;
|
||||
}
|
||||
@ -88,9 +91,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,16 +80,16 @@ 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);
|
||||
$tile = new TileChest($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
|
||||
if($chest instanceof TileChest){
|
||||
$chest->pairWith($tile);
|
||||
@ -92,7 +104,7 @@ class Chest extends Transparent{
|
||||
if($t instanceof TileChest){
|
||||
$t->unpair();
|
||||
}
|
||||
$this->getLevel()->setBlock($this, new Air(), true, true, true);
|
||||
$this->getLevel()->setBlock($this, new Air(), true, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -109,15 +121,15 @@ 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);
|
||||
$chest = new TileChest($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
|
||||
}
|
||||
|
||||
|
||||
@ -131,19 +143,8 @@ class Chest extends Transparent{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
$drops = array(
|
||||
array($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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $drops;
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -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 [];
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ class CyanFlower extends Flowable{
|
||||
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;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ class Dandelion extends Flowable{
|
||||
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],
|
||||
];
|
||||
}
|
||||
}
|
@ -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 [];
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ class Dirt extends Solid{
|
||||
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,9 +21,22 @@
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
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,14 +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{
|
||||
abstract class Fallable extends Solid{
|
||||
|
||||
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()->getChunk($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){
|
||||
@ -37,6 +40,14 @@ class Fire extends Flowable{
|
||||
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 [];
|
||||
@ -50,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;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class Flowable extends Transparent{
|
||||
abstract class Flowable extends Transparent{
|
||||
|
||||
public $isFlowable = true;
|
||||
public $isFullBlock = false;
|
||||
|
@ -28,7 +28,7 @@ use pocketmine\Player;
|
||||
class Generic extends Block{
|
||||
|
||||
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){
|
||||
@ -36,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,7 +22,7 @@
|
||||
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\level\Position;
|
||||
use pocketmine\Player;
|
||||
@ -65,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,22 +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;
|
||||
}
|
||||
@ -70,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){
|
||||
@ -37,123 +39,21 @@ class Lava extends Liquid{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
$entity->fallDistance *= 0.5;
|
||||
$entity->setOnFire(15);
|
||||
$ev = new EntityDamageEvent($entity, EntityDamageEvent::CAUSE_LAVA, 4);
|
||||
Server::getInstance()->getPluginManager()->callEvent($ev);
|
||||
if(!$ev->isCancelled()){
|
||||
$entity->attack($ev->getFinalDamage(), $ev);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
$this->getLevel()->scheduleUpdate(clone $this, 40);
|
||||
$ret = $this->getLevel()->setBlock($this, $this, true, false);
|
||||
$this->getLevel()->scheduleUpdate($this, $this->tickRate());
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function getSourceCount(){
|
||||
$count = 0;
|
||||
for($side = 2; $side <= 5; ++$side){
|
||||
if($this->getSide($side) instanceof Lava){
|
||||
$b = $this->getSide($side);
|
||||
$level = $b->meta & 0x07;
|
||||
if($level == 0x00){
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
public function checkWater(){
|
||||
for($side = 1; $side <= 5; ++$side){
|
||||
$b = $this->getSide($side);
|
||||
if($b instanceof Water){
|
||||
$level = $this->meta & 0x07;
|
||||
if($level == 0x00){
|
||||
$this->getLevel()->setBlock($this, new Obsidian(), false, false, true);
|
||||
}else{
|
||||
$this->getLevel()->setBlock($this, new Cobblestone(), false, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getFrom(){
|
||||
for($side = 0; $side <= 5; ++$side){
|
||||
$b = $this->getSide($side);
|
||||
if($b instanceof Lava){
|
||||
$tlevel = $b->meta & 0x07;
|
||||
$level = $this->meta & 0x07;
|
||||
if(($tlevel + 2) == $level || ($side == 0x01 && $level == 0x01) || ($tlevel == 6 && $level == 7)){
|
||||
return $b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
return false;
|
||||
$newId = $this->id;
|
||||
$level = $this->meta & 0x07;
|
||||
if($type !== Level::BLOCK_UPDATE_NORMAL){
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->checkWater()){
|
||||
return;
|
||||
}
|
||||
|
||||
$falling = $this->meta >> 3;
|
||||
$down = $this->getSide(0);
|
||||
|
||||
$from = $this->getFrom();
|
||||
if($from !== null || $level == 0x00){
|
||||
if($level !== 0x07){
|
||||
if($down instanceof Air || $down instanceof Lava){
|
||||
$this->getLevel()->setBlock($down, new Lava(0x01), false, false, true);
|
||||
Server::getInstance()->api->block->scheduleBlockUpdate(new Position($down, 0, 0, $this->level), 40, Level::BLOCK_UPDATE_NORMAL);
|
||||
}else{
|
||||
for($side = 2; $side <= 5; ++$side){
|
||||
$b = $this->getSide($side);
|
||||
if($b instanceof Lava){
|
||||
|
||||
}elseif($b->isFlowable === true){
|
||||
$this->getLevel()->setBlock($b, new Lava(min($level + 2, 7)), false, false, true);
|
||||
Server::getInstance()->api->block->scheduleBlockUpdate(Position::fromObject($b, $this->level), 40, Level::BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
//Extend Remove for Left Lavas
|
||||
for($side = 2; $side <= 5; ++$side){
|
||||
$sb = $this->getSide($side);
|
||||
if($sb instanceof Lava){
|
||||
$tlevel = $sb->meta & 0x07;
|
||||
if($tlevel != 0x00){
|
||||
for($s = 0; $s <= 5; $s++){
|
||||
$ssb = $sb->getSide($s);
|
||||
Server::getInstance()->api->block->scheduleBlockUpdate(Position::fromObject($ssb, $this->level), 40, Level::BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
$this->getLevel()->setBlock($sb, new Air(), false, false, true);
|
||||
}
|
||||
}
|
||||
$b = $this->getSide(0)->getSide($side);
|
||||
if($b instanceof Lava){
|
||||
$tlevel = $b->meta & 0x07;
|
||||
if($tlevel != 0x00){
|
||||
for($s = 0; $s <= 5; $s++){
|
||||
$ssb = $sb->getSide($s);
|
||||
Server::getInstance()->api->block->scheduleBlockUpdate(Position::fromObject($ssb, $this->level), 40, Level::BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
$this->getLevel()->setBlock($b, new Air(), false, false, true);
|
||||
}
|
||||
}
|
||||
//Server::getInstance()->api->block->scheduleBlockUpdate(Position::fromObject($b, $this->level), 10, Level::BLOCK_UPDATE_NORMAL);
|
||||
}
|
||||
|
||||
$this->getLevel()->setBlock($this, new Air(), false, false, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,10 +22,390 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class Liquid extends Transparent{
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
|
||||
abstract class Liquid extends Transparent{
|
||||
public $isLiquid = true;
|
||||
public $breakable = false;
|
||||
public $isReplaceable = true;
|
||||
public $isSolid = false;
|
||||
public $isFullBlock = true;
|
||||
|
||||
public $adjacentSources = 0;
|
||||
public $isOptimalFlowDirection = [0, 0, 0];
|
||||
public $flowCost = [0, 0, 0];
|
||||
|
||||
public function getFluidHeightPercent(){
|
||||
$d = $this->meta;
|
||||
if($d >= 8){
|
||||
$d = 0;
|
||||
}
|
||||
|
||||
return ($d + 1) / 9;
|
||||
}
|
||||
|
||||
protected function getFlowDecay(Vector3 $pos){
|
||||
if(!($pos instanceof Block)){
|
||||
$pos = $this->getLevel()->getBlock($pos);
|
||||
}
|
||||
|
||||
if($pos->getID() !== $this->getID()){
|
||||
return -1;
|
||||
}else{
|
||||
return $pos->getDamage();
|
||||
}
|
||||
}
|
||||
|
||||
protected function getEffectiveFlowDecay(Vector3 $pos){
|
||||
if(!($pos instanceof Block)){
|
||||
$pos = $this->getLevel()->getBlock($pos);
|
||||
}
|
||||
|
||||
if($pos->getID() !== $this->getID()){
|
||||
return -1;
|
||||
}
|
||||
|
||||
$decay = $pos->getDamage();
|
||||
|
||||
if($decay >= 8){
|
||||
$decay = 0;
|
||||
}
|
||||
|
||||
return $decay;
|
||||
}
|
||||
|
||||
public function getFlowVector(){
|
||||
$vector = new Vector3(0, 0, 0);
|
||||
|
||||
$decay = $this->getEffectiveFlowDecay($this);
|
||||
|
||||
for($j = 0; $j < 4; ++$j){
|
||||
|
||||
$x = $this->x;
|
||||
$y = $this->y;
|
||||
$z = $this->z;
|
||||
|
||||
if($j === 0){
|
||||
--$x;
|
||||
}elseif($j === 1){
|
||||
++$x;
|
||||
}elseif($j === 2){
|
||||
--$z;
|
||||
}elseif($j === 3){
|
||||
++$z;
|
||||
}
|
||||
$sideBlock = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
|
||||
$blockDecay = $this->getEffectiveFlowDecay($sideBlock);
|
||||
|
||||
if($blockDecay < 0){
|
||||
if(!$sideBlock->isFlowable){
|
||||
continue;
|
||||
}
|
||||
|
||||
$blockDecay = $this->getEffectiveFlowDecay($sideBlock->getSide(0));
|
||||
|
||||
if($blockDecay >= 0){
|
||||
$realDecay = $blockDecay - ($decay - 8);
|
||||
$vector = $vector->add(($sideBlock->x - $this->x) * $realDecay, ($sideBlock->y - $this->y) * $realDecay, ($sideBlock->z - $this->z) * $realDecay);
|
||||
}
|
||||
|
||||
continue;
|
||||
}else{
|
||||
$realDecay = $blockDecay - $decay;
|
||||
$vector = $vector->add(($sideBlock->x - $this->x) * $realDecay, ($sideBlock->y - $this->y) * $realDecay, ($sideBlock->z - $this->z) * $realDecay);
|
||||
}
|
||||
}
|
||||
|
||||
if($this->getDamage() >= 8){
|
||||
$falling = false;
|
||||
|
||||
if(!$this->getLevel()->getBlock($this->add(0, 0, -1))->isFlowable){
|
||||
$falling = true;
|
||||
}elseif(!$this->getLevel()->getBlock($this->add(0, 0, 1))->isFlowable){
|
||||
$falling = true;
|
||||
}elseif(!$this->getLevel()->getBlock($this->add(-1, 0, 0))->isFlowable){
|
||||
$falling = true;
|
||||
}elseif(!$this->getLevel()->getBlock($this->add(1, 0, 0))->isFlowable){
|
||||
$falling = true;
|
||||
}elseif(!$this->getLevel()->getBlock($this->add(0, 1, -1))->isFlowable){
|
||||
$falling = true;
|
||||
}elseif(!$this->getLevel()->getBlock($this->add(0, 1, 1))->isFlowable){
|
||||
$falling = true;
|
||||
}elseif(!$this->getLevel()->getBlock($this->add(-1, 1, 0))->isFlowable){
|
||||
$falling = true;
|
||||
}elseif(!$this->getLevel()->getBlock($this->add(1, 1, 0))->isFlowable){
|
||||
$falling = true;
|
||||
}
|
||||
|
||||
if($falling){
|
||||
$vector = $vector->normalize()->add(0, -6, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return $vector->normalize();
|
||||
}
|
||||
|
||||
public function addVelocityToEntity(Entity $entity, Vector3 $vector){
|
||||
$flow = $this->getFlowVector();
|
||||
$vector->x += $flow->x;
|
||||
$vector->y += $flow->y;
|
||||
$vector->z += $flow->z;
|
||||
}
|
||||
|
||||
public function tickRate(){
|
||||
if($this instanceof Water){
|
||||
return 5;
|
||||
}elseif($this instanceof Lava){
|
||||
return 30;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function onUpdate($type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
$this->checkForHarden();
|
||||
$this->getLevel()->scheduleUpdate($this, $this->tickRate());
|
||||
}elseif($type === Level::BLOCK_UPDATE_SCHEDULED){
|
||||
$decay = $this->getFlowDecay($this);
|
||||
$multiplier = $this instanceof Lava ? 2 : 1;
|
||||
|
||||
$flag = true;
|
||||
|
||||
if($decay > 0){
|
||||
$smallestFlowDecay = -100;
|
||||
$this->adjacentSources = 0;
|
||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->getSide(4), $smallestFlowDecay);
|
||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->getSide(5), $smallestFlowDecay);
|
||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->getSide(2), $smallestFlowDecay);
|
||||
$smallestFlowDecay = $this->getSmallestFlowDecay($this->getSide(3), $smallestFlowDecay);
|
||||
|
||||
$k = $smallestFlowDecay + $multiplier;
|
||||
|
||||
if($k >= 8 or $smallestFlowDecay < 0){
|
||||
$k = -1;
|
||||
}
|
||||
|
||||
if(($topFlowDecay = $this->getFlowDecay($this->getSide(1))) >= 0){
|
||||
if($topFlowDecay >= 8){
|
||||
$k = $topFlowDecay;
|
||||
}else{
|
||||
$k = $topFlowDecay | 0x08;
|
||||
}
|
||||
}
|
||||
|
||||
if($this->adjacentSources >= 2 and $this instanceof Water){
|
||||
$bottomBlock = $this->getSide(0);
|
||||
if($bottomBlock->isSolid){
|
||||
$k = 0;
|
||||
}elseif($bottomBlock instanceof Water and $bottomBlock->getDamage() === 0){
|
||||
$k = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if($this instanceof Lava and $decay < 8 and $k < 8 and $k > 1 and mt_rand(0, 4) !== 0){
|
||||
$k = $decay;
|
||||
$flag = false;
|
||||
}
|
||||
|
||||
if($k !== $decay){
|
||||
$decay = $k;
|
||||
if($decay < 0){
|
||||
$this->getLevel()->setBlock($this, Block::get(Item::AIR), true);
|
||||
}else{
|
||||
$this->getLevel()->setBlock($this, Block::get($this->id, $decay), true);
|
||||
$this->getLevel()->scheduleUpdate($this, $this->tickRate());
|
||||
}
|
||||
}elseif($flag){
|
||||
$this->getLevel()->scheduleUpdate($this, $this->tickRate());
|
||||
//$this->updateFlow();
|
||||
}
|
||||
}else{
|
||||
//$this->updateFlow();
|
||||
}
|
||||
|
||||
$bottomBlock = $this->getSide(0);
|
||||
|
||||
if($bottomBlock->isFlowable or $bottomBlock instanceof Liquid){
|
||||
if($this instanceof Lava and $bottomBlock instanceof Water){
|
||||
$this->getLevel()->setBlock($bottomBlock, Block::get(Item::STONE), true);
|
||||
return;
|
||||
}
|
||||
|
||||
if($decay >= 8){
|
||||
$this->getLevel()->setBlock($bottomBlock, Block::get($this->id, $decay), true);
|
||||
$this->getLevel()->scheduleUpdate($bottomBlock, $this->tickRate());
|
||||
}else{
|
||||
$this->getLevel()->setBlock($bottomBlock, Block::get($this->id, $decay + 8), true);
|
||||
$this->getLevel()->scheduleUpdate($bottomBlock, $this->tickRate());
|
||||
}
|
||||
}elseif($decay >= 0 and ($decay === 0 or !$bottomBlock->isFlowable)){
|
||||
$flags = $this->getOptimalFlowDirections();
|
||||
|
||||
$l = $decay + $multiplier;
|
||||
|
||||
if($decay >= 8){
|
||||
$l = 1;
|
||||
}
|
||||
|
||||
if($l >= 8){
|
||||
$this->checkForHarden();
|
||||
return;
|
||||
}
|
||||
|
||||
if($flags[0]){
|
||||
$this->flowIntoBlock($this->getSide(4), $l);
|
||||
}
|
||||
|
||||
if($flags[1]){
|
||||
$this->flowIntoBlock($this->getSide(5), $l);
|
||||
}
|
||||
|
||||
if($flags[2]){
|
||||
$this->flowIntoBlock($this->getSide(2), $l);
|
||||
}
|
||||
|
||||
if($flags[3]){
|
||||
$this->flowIntoBlock($this->getSide(3), $l);
|
||||
}
|
||||
}
|
||||
|
||||
$this->checkForHarden();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private function flowIntoBlock(Block $block, $newFlowDecay){
|
||||
if($block->isFlowable){
|
||||
if($block->getID() > 0){
|
||||
$this->getLevel()->useBreakOn($block);
|
||||
}
|
||||
|
||||
$this->getLevel()->setBlock($block, Block::get($this->id, $newFlowDecay), true);
|
||||
$this->getLevel()->scheduleUpdate($block, $this->tickRate());
|
||||
}
|
||||
}
|
||||
|
||||
private function calculateFlowCost(Block $block, $accumulatedCost, $previousDirection){
|
||||
$cost = 1000;
|
||||
|
||||
for($j = 0; $j < 4; ++$j){
|
||||
if(
|
||||
($j === 0 and $previousDirection === 1) or
|
||||
($j === 1 and $previousDirection === 0) or
|
||||
($j === 2 and $previousDirection === 3) or
|
||||
($j === 3 and $previousDirection === 2)
|
||||
){
|
||||
$x = $block->x;
|
||||
$y = $block->y;
|
||||
$z = $block->z;
|
||||
|
||||
if($j === 0){
|
||||
--$x;
|
||||
}elseif($j === 1){
|
||||
++$x;
|
||||
}elseif($j === 2){
|
||||
--$z;
|
||||
}elseif($j === 3){
|
||||
++$z;
|
||||
}
|
||||
$blockSide = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
|
||||
|
||||
if(!$blockSide->isFlowable or ($blockSide instanceof Liquid and $blockSide->getDamage() === 0)){
|
||||
continue;
|
||||
}elseif($blockSide->getSide(0)->isFlowable){
|
||||
return $accumulatedCost;
|
||||
}
|
||||
|
||||
if($accumulatedCost >= 4){
|
||||
continue;
|
||||
}
|
||||
|
||||
$realCost = $this->calculateFlowCost($blockSide, $accumulatedCost + 1, $j);
|
||||
|
||||
if($realCost < $cost){
|
||||
$cost = $realCost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $cost;
|
||||
}
|
||||
|
||||
private function getOptimalFlowDirections(){
|
||||
for($j = 0; $j < 4; ++$j){
|
||||
$this->flowCost[$j] = 1000;
|
||||
|
||||
$x = $this->x;
|
||||
$y = $this->y;
|
||||
$z = $this->z;
|
||||
|
||||
if($j === 0){
|
||||
--$x;
|
||||
}elseif($j === 1){
|
||||
++$x;
|
||||
}elseif($j === 2){
|
||||
--$z;
|
||||
}elseif($j === 3){
|
||||
++$z;
|
||||
}
|
||||
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
|
||||
|
||||
if(!$block->isFlowable or ($block instanceof Liquid and $block->getDamage() === 0)){
|
||||
continue;
|
||||
}elseif($block->getSide(0)->isFlowable){
|
||||
$this->flowCost[$j] = 0;
|
||||
}else{
|
||||
$this->flowCost[$j] = $this->calculateFlowCost($block, 1, $j);
|
||||
}
|
||||
}
|
||||
|
||||
$minCost = $this->flowCost[0];
|
||||
|
||||
for($i = 1; $i < 4; ++$i){
|
||||
if($this->flowCost[$i] < $minCost){
|
||||
$minCost = $this->flowCost[$i];
|
||||
}
|
||||
}
|
||||
|
||||
for($i = 0; $i < 4; ++$i){
|
||||
$this->isOptimalFlowDirection[$i] = ($this->flowCost[$i] === $minCost);
|
||||
}
|
||||
|
||||
return $this->isOptimalFlowDirection;
|
||||
}
|
||||
|
||||
private function getSmallestFlowDecay(Vector3 $pos, $decay){
|
||||
$blockDecay = $this->getFlowDecay($pos);
|
||||
|
||||
if($blockDecay < 0){
|
||||
return $decay;
|
||||
}elseif($blockDecay === 0){
|
||||
++$this->adjacentSources;
|
||||
}elseif($blockDecay >= 8){
|
||||
$blockDecay = 0;
|
||||
}
|
||||
|
||||
return ($decay >= 0 && $blockDecay >= $decay) ? $decay : $blockDecay;
|
||||
}
|
||||
|
||||
private function checkForHarden(){
|
||||
if($this instanceof Lava){
|
||||
$colliding = false;
|
||||
for($side = 0; $side <= 5 and !$colliding; ++$side){
|
||||
$colliding = $this->getSide($side) instanceof Water;
|
||||
}
|
||||
|
||||
if($colliding){
|
||||
if($this->getDamage() === 0){
|
||||
$this->getLevel()->setBlock($this, Block::get(Item::OBSIDIAN), true);
|
||||
}elseif($this->getDamage() <= 4){
|
||||
$this->getLevel()->setBlock($this, Block::get(Item::COBBLESTONE), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)],
|
||||
];
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@ class MelonStem extends Flowable{
|
||||
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;
|
||||
}
|
||||
@ -60,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{
|
||||
@ -73,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -87,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--;
|
||||
}
|
||||
@ -99,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 [];
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class Potato extends Flowable{
|
||||
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;
|
||||
}
|
||||
@ -50,8 +50,11 @@ 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->meta += mt_rand(2, 5);
|
||||
if($this->meta > 7){
|
||||
$this->meta = 7;
|
||||
}
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
if(($player->gamemode & 0x01) === 0){
|
||||
$item->count--;
|
||||
}
|
||||
@ -74,7 +77,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;
|
||||
}
|
||||
@ -89,9 +92,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;
|
||||
}
|
||||
|
||||
}
|
@ -40,7 +40,7 @@ class PumpkinStem extends Flowable{
|
||||
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;
|
||||
}
|
||||
@ -61,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{
|
||||
@ -74,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -88,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--;
|
||||
}
|
||||
@ -100,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 [];
|
||||
}
|
||||
|
@ -53,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,14 +37,14 @@ 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;
|
||||
}
|
||||
@ -57,7 +57,7 @@ class Sapling extends Flowable{
|
||||
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;
|
||||
}
|
||||
@ -94,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;
|
||||
}
|
||||
@ -107,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],
|
||||
];
|
||||
}
|
||||
}
|
@ -40,20 +40,20 @@ class SignPost extends Transparent{
|
||||
|
||||
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;
|
||||
}
|
||||
@ -83,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,19 +85,19 @@ 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;
|
||||
}
|
||||
//TODO: check for collision
|
||||
}elseif(!($player instanceof Player)){
|
||||
}else{
|
||||
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;
|
||||
}
|
||||
@ -85,13 +108,12 @@ class Slab extends Transparent{
|
||||
$this->meta |= 0x08;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
|
||||
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 +138,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 [];
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ class SnowLayer extends Flowable{
|
||||
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;
|
||||
}
|
||||
@ -53,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;
|
||||
}
|
||||
@ -64,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,7 +22,7 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class Solid extends Generic{
|
||||
abstract class Solid extends Generic{
|
||||
|
||||
public function __construct($id, $meta = 0, $name = "Unknown"){
|
||||
parent::__construct($id, $meta, $name);
|
||||
|
@ -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,9 +22,10 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\Player;
|
||||
|
||||
class Stair extends Transparent{
|
||||
abstract class Stair extends Transparent{
|
||||
|
||||
public function __construct($id, $meta = 0, $name = "Unknown"){
|
||||
parent::__construct($id, $meta, $name);
|
||||
@ -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,11 +21,18 @@
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\entity\Entity;
|
||||
|
||||
class StillLava extends Liquid{
|
||||
class StillLava extends Lava{
|
||||
public function __construct($meta = 0){
|
||||
parent::__construct(self::STILL_LAVA, $meta, "Still Lava");
|
||||
$this->hardness = 500;
|
||||
}
|
||||
|
||||
public function getBoundingBox(){
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -21,7 +21,6 @@
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
class StillWater extends Water{
|
||||
public function __construct($meta = 0){
|
||||
Liquid::__construct(self::STILL_WATER, $meta, "Still Water");
|
||||
|
@ -68,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 [];
|
||||
}
|
||||
|
@ -22,6 +22,8 @@
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
class StoneWall extends Transparent{
|
||||
public function __construct($meta = 0){
|
||||
$meta &= 0x01;
|
||||
@ -34,4 +36,40 @@ class StoneWall extends Transparent{
|
||||
$this->hardness = 30;
|
||||
}
|
||||
|
||||
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.25;
|
||||
$f1 = $flag3 ? 1 : 0.75;
|
||||
$f2 = $flag ? 0 : 0.25;
|
||||
$f3 = $flag1 ? 1 : 0.75;
|
||||
$f4 = 1;
|
||||
|
||||
if($flag and $flag1 and !$flag2 and !$flag3){
|
||||
$f4 = 0.8125;
|
||||
$f = 0.3125;
|
||||
$f1 = 0.6875;
|
||||
}elseif(!$flag and !$flag1 and $flag2 and $flag3){
|
||||
$f4 = 0.8125;
|
||||
$f2 = 0.3125;
|
||||
$f3 = 0.6875;
|
||||
}
|
||||
|
||||
return new AxisAlignedBB(
|
||||
$this->x + $f,
|
||||
$this->y,
|
||||
$this->z + $f2,
|
||||
$this->x + $f1,
|
||||
$this->y + $f4,
|
||||
$this->z + $f3
|
||||
);
|
||||
}
|
||||
|
||||
public function canConnect(Block $block){
|
||||
return ($block->getID() !== self::COBBLE_WALL and $block->getID() !== self::FENCE_GATE) ? $block->isSolid : true;
|
||||
}
|
||||
|
||||
}
|
@ -40,8 +40,8 @@ class Stonecutter extends Solid{
|
||||
}
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array($this->id, 0, 1),
|
||||
);
|
||||
return [
|
||||
[$this->id, 0, 1],
|
||||
];
|
||||
}
|
||||
}
|
@ -38,9 +38,9 @@ class Sugarcane extends Flowable{
|
||||
|
||||
|
||||
public function getDrops(Item $item){
|
||||
return array(
|
||||
array(Item::SUGARCANE, 0, 1),
|
||||
);
|
||||
return [
|
||||
[Item::SUGARCANE, 0, 1],
|
||||
];
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null){
|
||||
@ -49,12 +49,12 @@ class Sugarcane extends Flowable{
|
||||
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 Sugarcane(), true, false, true);
|
||||
$this->getLevel()->setBlock($b, new Sugarcane(), true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->meta = 0;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
}
|
||||
if(($player->gamemode & 0x01) === 0){
|
||||
$item->count--;
|
||||
@ -82,15 +82,15 @@ class Sugarcane extends Flowable{
|
||||
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 Sugarcane(), true, false, true);
|
||||
$this->getLevel()->setBlock($b, new Sugarcane(), true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->meta = 0;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
}else{
|
||||
++$this->meta;
|
||||
$this->getLevel()->setBlock($this, $this, true, false, true);
|
||||
$this->getLevel()->setBlock($this, $this, true);
|
||||
}
|
||||
|
||||
return Level::BLOCK_UPDATE_RANDOM;
|
||||
@ -103,7 +103,7 @@ class Sugarcane extends Flowable{
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
$down = $this->getSide(0);
|
||||
if($down->getID() === self::SUGARCANE_BLOCK){
|
||||
$this->getLevel()->setBlock($block, new Sugarcane(), true, false, true);
|
||||
$this->getLevel()->setBlock($block, new Sugarcane(), true);
|
||||
|
||||
return true;
|
||||
}elseif($down->getID() === self::GRASS or $down->getID() === self::DIRT or $down->getID() === self::SAND){
|
||||
@ -112,7 +112,7 @@ class Sugarcane extends Flowable{
|
||||
$block2 = $down->getSide(4);
|
||||
$block3 = $down->getSide(5);
|
||||
if(($block0 instanceof Water) or ($block1 instanceof Water) or ($block2 instanceof Water) or ($block3 instanceof Water)){
|
||||
$this->getLevel()->setBlock($block, new Sugarcane(), true, false, true);
|
||||
$this->getLevel()->setBlock($block, new Sugarcane(), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -36,13 +36,13 @@ class TNT extends Solid{
|
||||
if(($player->gamemode & 0x01) === 0){
|
||||
$item->useOn($this);
|
||||
}
|
||||
$data = array(
|
||||
$data = [
|
||||
"x" => $this->x + 0.5,
|
||||
"y" => $this->y + 0.5,
|
||||
"z" => $this->z + 0.5,
|
||||
"power" => 4,
|
||||
"fuse" => 20 * 4, //4 seconds
|
||||
);
|
||||
];
|
||||
$this->getLevel()->setBlock($this, new Air(), false, false, true);
|
||||
//TODO
|
||||
//$e = Server::getInstance()->api->entity->add($this->level, ENTITY_OBJECT, OBJECT_PRIMEDTNT, $data);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user