mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-10 19:48:13 +00:00
Compare commits
266 Commits
api/3.0.0-
...
api/3.0.0-
Author | SHA1 | Date | |
---|---|---|---|
a1ce535d02 | |||
993af0fa30 | |||
b83c135c3f | |||
8bf1cc9e48 | |||
c70690a600 | |||
4b4f2af9e3 | |||
9047c2c1ef | |||
89ca2ac2d5 | |||
6a2a74a457 | |||
7ba807fd42 | |||
19410754c6 | |||
8cd31c2dc4 | |||
c09a5ab301 | |||
a0ef15b15e | |||
03826d9cbc | |||
080b35bf53 | |||
e9c46da7f0 | |||
0f79b19fdc | |||
69ae37d191 | |||
86742fcf30 | |||
a4b8dd43e6 | |||
e11f1e94e9 | |||
938452bfe9 | |||
a724395148 | |||
bc10edfdd3 | |||
f7d07ca155 | |||
be7b057fa5 | |||
8637e0224f | |||
8919d4a372 | |||
0cf3914f5d | |||
e9a638d84a | |||
e3b3f60c66 | |||
1bae973502 | |||
e0f8a02bb8 | |||
846be84324 | |||
8ef24423d1 | |||
8fc38c36f9 | |||
eb05f2ecde | |||
478e954b3f | |||
313fdb9e87 | |||
1bf18ba8d2 | |||
5011198a4e | |||
e96fa8b682 | |||
bf3868c078 | |||
3167817e34 | |||
433b8369f5 | |||
0612244b5e | |||
487233a101 | |||
4341fb8347 | |||
789df942b6 | |||
9e99252817 | |||
75cc2d6914 | |||
61b857a81c | |||
2024e9ecdf | |||
4765242397 | |||
3687b149b9 | |||
1aae9e03b6 | |||
c43ab12a9a | |||
cd66f58526 | |||
7870a8672e | |||
eac756470a | |||
a302b4988f | |||
2193adf844 | |||
890f72dbf2 | |||
595e1ab52f | |||
4a7abb7033 | |||
d358e13868 | |||
1f630e57f2 | |||
cc1d1b0f45 | |||
78c09267e5 | |||
c445db421f | |||
e18a3ac933 | |||
75863e2a44 | |||
5aea9220c9 | |||
bd7205dd64 | |||
82a63ed18e | |||
cf07af8b55 | |||
b775e8c88a | |||
51091fe87b | |||
7c14ffbcfa | |||
db93827650 | |||
c2186041d6 | |||
481114281e | |||
51b0673b4b | |||
606b9b687d | |||
45618c7cfe | |||
3f03d9e683 | |||
f0d12a0b30 | |||
9cc27b2719 | |||
87e54d7a3a | |||
29e88d8592 | |||
c6e800cf42 | |||
b7b7bcee4f | |||
6ea0eb47ec | |||
b9a87ed147 | |||
742f593758 | |||
1e9ff44890 | |||
55c4e35407 | |||
e83ffd5afe | |||
54453d0b0a | |||
51d510aa4f | |||
4cd97a7c7a | |||
d586ad03ec | |||
61d354a4ea | |||
6f126ad239 | |||
efea39e0a4 | |||
d4bb078566 | |||
6686bd4442 | |||
2b02fcfe2c | |||
138fb88431 | |||
26577d9d5b | |||
2f4943ac90 | |||
eda7965f86 | |||
4666560731 | |||
b01ad01eff | |||
4ba3a3af3d | |||
5baf59ca56 | |||
902957cb53 | |||
3463bea932 | |||
105917a534 | |||
b83082f224 | |||
840a3883b1 | |||
ad4659365a | |||
8d858e3e6d | |||
22ba017965 | |||
8bb0e8d398 | |||
087a994393 | |||
e4e4ef5f2a | |||
3ac51e1095 | |||
2db6ea6b18 | |||
b6ae92e1a7 | |||
31e2c1d26c | |||
846e3b6f1e | |||
0e525ac1c3 | |||
8382970d56 | |||
db3cd1829c | |||
caced595d2 | |||
86f3b257a7 | |||
1ed5de1d3b | |||
63358a8065 | |||
f6ff03fc31 | |||
0ad16c1919 | |||
38b8f14758 | |||
8779259734 | |||
2f306c3a38 | |||
57379b93ce | |||
954271b90f | |||
645d744e05 | |||
4c764072b2 | |||
3446f68c74 | |||
ca6826898b | |||
76ab3d4288 | |||
b6c1139b27 | |||
af06d78725 | |||
8cc1003956 | |||
92281da514 | |||
5c8297f4a1 | |||
23ed3334c2 | |||
674394c4f5 | |||
4e381ab033 | |||
c5527db424 | |||
aecff7c782 | |||
0207b22110 | |||
a77c1ce13c | |||
afd90adb1c | |||
2e480b5ea1 | |||
d4cc7d13cd | |||
f6c0ba9846 | |||
f3c38700f5 | |||
77b1b565a4 | |||
36c95660e6 | |||
905d3f1610 | |||
0f174f7605 | |||
60f5c7ccef | |||
85c1535c75 | |||
568e2760f1 | |||
fe8cb8cd86 | |||
15b47fcb2f | |||
00e6d6a6b1 | |||
8887a92d4b | |||
a9afad10bc | |||
b41fef0276 | |||
fe3b5bac51 | |||
0a4d62b405 | |||
0935855def | |||
c7c7a40899 | |||
162a08b8cb | |||
b9ad0b99a5 | |||
576702ffa9 | |||
dbb8e8ad0a | |||
4a9acf564c | |||
69f64dd802 | |||
11169b0777 | |||
71af694cc1 | |||
c51c8ae700 | |||
713f3facf9 | |||
df577bddc2 | |||
046f17c9e2 | |||
50f7d04044 | |||
4ccd955647 | |||
c383c7b0dd | |||
adbb53929e | |||
8a7259aa73 | |||
76ceddf266 | |||
11f35d28c2 | |||
c4f461f65d | |||
702c129a97 | |||
56306f6636 | |||
18f1376c65 | |||
49eb0eb050 | |||
13fd8b681e | |||
40f2d7fcdc | |||
c537cea87e | |||
eaef2bd169 | |||
966e4bf8a1 | |||
f889bf9cf5 | |||
6d90f91be0 | |||
0a52e210db | |||
971703a618 | |||
de359a2bce | |||
1266f8f1aa | |||
a22306d418 | |||
b542277eca | |||
edf1fbb6e6 | |||
653b6b55a9 | |||
7f09a2a26e | |||
7aeb3129ac | |||
dc71eb5246 | |||
bf9b8722c9 | |||
4d897b824b | |||
caf4937222 | |||
2f87dfdcb0 | |||
ffcada88f3 | |||
946d7e2bb1 | |||
7a2ed232cc | |||
1be4bd67e4 | |||
fcff6961a8 | |||
db4027cdb2 | |||
e22bb213af | |||
179210aa27 | |||
be631ad6f7 | |||
3f1790bcb8 | |||
a0ba8f0098 | |||
feb538900b | |||
5ce860c2f5 | |||
6c5ca9b256 | |||
17e4f45e97 | |||
6828ce66b6 | |||
b7b7a93e4e | |||
a34573643f | |||
dab73d8950 | |||
5e6a0e7ba0 | |||
c5eccc8e1c | |||
b55929b382 | |||
d7378fe6f4 | |||
66924729ff | |||
f12a6eed29 | |||
a327a74ece | |||
f3ab45e7d5 | |||
cdf6d200ef | |||
894beed59b | |||
022f33b256 | |||
90f1efc667 | |||
f7e959d602 | |||
9c25ec3afd | |||
e47c7ea55f |
17
.github/ISSUE_TEMPLATE.md
vendored
17
.github/ISSUE_TEMPLATE.md
vendored
@ -16,15 +16,26 @@ Actual result: What actually happened?
|
||||
|
||||
### OS and versions
|
||||
<!--- use the 'version' command in PocketMine-MP
|
||||
NOTE: LATEST is not a valid version.
|
||||
PocketMine version should include Jenkins build number and/or git commit hash.
|
||||
ALSO NOTE: NO support whatsoever will be provided for forks or spoons of PocketMine. Issues relating to non-official distributions will be closed as spam. Please send such issues to whoever is responsible for the fork or spoon you are using.
|
||||
|
||||
NOTE: LATEST is not a valid version. PocketMine version should include Jenkins build number and/or git commit hash.
|
||||
|
||||
NO support whatsoever will be provided for forks or spoons of PocketMine. Issues relating to non-official distributions will be closed as spam. Please send such issues to whoever is responsible for the fork or spoon you are using.
|
||||
|
||||
Note that 32-bit platforms are no longer supported by PocketMine-MP and issues concerning 32-bit platforms will be closed.
|
||||
-->
|
||||
* PocketMine-MP:
|
||||
* PHP:
|
||||
* Server OS:
|
||||
* Game version: PE/Win10 (delete as appropriate)
|
||||
|
||||
### Plugins
|
||||
- Test on a clean server without plugins: is the issue reproducible without any plugins loaded?
|
||||
|
||||
If the issue is **not** reproducible without plugins:
|
||||
- Have you asked for help on our forums before creating an issue?
|
||||
- Can you provide sample, *minimal* reproducing code for the issue? If so, paste it in the bottom section
|
||||
- Paste your list of plugins here (use the 'plugins' command in PocketMine-MP)
|
||||
|
||||
### Crashdump, backtrace or other files
|
||||
<!--- please use gist or anything else and add links here -->
|
||||
* ...
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -14,3 +14,6 @@
|
||||
[submodule "tests/plugins/PocketMine-DevTools"]
|
||||
path = tests/plugins/PocketMine-DevTools
|
||||
url = https://github.com/pmmp/PocketMine-DevTools.git
|
||||
[submodule "tests/plugins/PocketMine-TesterPlugin"]
|
||||
path = tests/plugins/PocketMine-TesterPlugin
|
||||
url = https://github.com/pmmp/PocketMine-TesterPlugin.git
|
||||
|
@ -18,8 +18,10 @@
|
||||
|
||||
- Information must be provided in the issue body, not in the title. No tags like `[BUG]` are allowed in the title, including `[SOLVED]` for solved issues.
|
||||
|
||||
- Similarly, no generic issue reports. For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**. If you do not provide us with a summary or instructions on how to reproduce the issue, it will be treated as spam and will therefore be closed.
|
||||
<br>In simple words, if your issue does not appear to be a bug or a feature request, or if the issue cannot be properly confirmed to be valid, the issue will be closed until further information is provided.
|
||||
- Similarly, no generic issue reports. For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**.
|
||||
<br><br>Valid issue reports must include instructions how to reproduce the issue or a crashdump/backtrace (unless the cause of the issue is obvious).
|
||||
<br><br>**If you do not provide us with a summary or instructions on how to reproduce the issue, it will be treated as spam and will therefore be closed.**
|
||||
<br><br>In simple words, if the issue cannot be properly confirmed to be valid or lacks required information, the issue will be closed until further information is provided.
|
||||
|
||||
- To express appreciation, objection, confusion or other supported reactions on pull requests, issues or comments on them, use GitHub [reactions](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) rather than posting an individual comment with an emoji only. This helps keeping the issue/pull request conversation clean and readable.
|
||||
|
||||
|
@ -13,7 +13,7 @@ If you don't find what you're looking for there, [talk to a human](#discussion).
|
||||
- [#pmmp + #pocketmine channel IRC](http://webchat.freenode.net/?channels=pmmp,pocketmine)
|
||||
|
||||
### Plugins
|
||||
There are a very wide range of already-written plugins available which you can use to customise your server. Check out [the old plugin repository](http://plugins.pocketmine.net/) and [Poggit](https://poggit.pmmp.io), or just search GitHub.
|
||||
There are a very wide range of already-written plugins available which you can use to customise your server. Check out [Poggit](https://poggit.pmmp.io), or just search GitHub.
|
||||
|
||||
### For developers
|
||||
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\event\TranslationContainer;
|
||||
@ -107,8 +109,8 @@ abstract class Achievement{
|
||||
|
||||
public static function broadcast(Player $player, $achievementId){
|
||||
if(isset(Achievement::$list[$achievementId])){
|
||||
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"]]);
|
||||
if(Server::getInstance()->getConfigString("announce-player-achievements", true) === true){
|
||||
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
|
||||
if(Server::getInstance()->getConfigBoolean("announce-player-achievements", true) === true){
|
||||
Server::getInstance()->broadcastMessage($translation);
|
||||
}else{
|
||||
$player->sendMessage($translation);
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
abstract class Collectable extends \Threaded implements \Collectable{
|
||||
|
@ -19,11 +19,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||
use pocketmine\plugin\PluginBase;
|
||||
use pocketmine\plugin\PluginLoadOrder;
|
||||
use pocketmine\plugin\PluginManager;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
use raklib\RakLib;
|
||||
@ -86,7 +89,7 @@ class CrashDump{
|
||||
}
|
||||
|
||||
private function pluginsData(){
|
||||
if(class_exists("pocketmine\\plugin\\PluginManager", false)){
|
||||
if($this->server->getPluginManager() instanceof PluginManager){
|
||||
$this->addLine();
|
||||
$this->addLine("Loaded plugins:");
|
||||
$this->data["plugins"] = [];
|
||||
@ -224,6 +227,7 @@ class CrashDump{
|
||||
private function generalData(){
|
||||
$version = new VersionString();
|
||||
$this->data["general"] = [];
|
||||
$this->data["general"]["name"] = $this->server->getName();
|
||||
$this->data["general"]["version"] = $version->get(false);
|
||||
$this->data["general"]["build"] = $version->getBuild();
|
||||
$this->data["general"]["protocol"] = ProtocolInfo::CURRENT_PROTOCOL;
|
||||
@ -235,7 +239,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->getBuild() . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
|
||||
$this->addLine($this->server->getName() . " version: " . $version->get(false) . " #" . $version->getBuild() . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
|
||||
$this->addLine("Git commit: " . GIT_COMMIT);
|
||||
$this->addLine("uname -a: " . php_uname("a"));
|
||||
$this->addLine("PHP Version: " . phpversion());
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\permission\ServerOperator;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\event\server\LowMemoryEvent;
|
||||
@ -90,7 +92,7 @@ class MemoryManager{
|
||||
$hardLimit = ((int) $this->server->getProperty("memory.main-hard-limit", $defaultMemory));
|
||||
|
||||
if($hardLimit <= 0){
|
||||
ini_set("memory_limit", -1);
|
||||
ini_set("memory_limit", '-1');
|
||||
}else{
|
||||
ini_set("memory_limit", $hardLimit . "M");
|
||||
}
|
||||
@ -214,6 +216,8 @@ class MemoryManager{
|
||||
}
|
||||
|
||||
public function dumpServerMemory($outputFolder, $maxNesting, $maxStringSize){
|
||||
$hardLimit = ini_get('memory_limit');
|
||||
ini_set('memory_limit', '-1');
|
||||
gc_disable();
|
||||
|
||||
if(!file_exists($outputFolder)){
|
||||
@ -232,6 +236,32 @@ class MemoryManager{
|
||||
|
||||
$refCounts = [];
|
||||
|
||||
$instanceCounts = [];
|
||||
|
||||
$staticCount = 0;
|
||||
foreach($this->server->getLoader()->getClasses() as $className){
|
||||
$reflection = new \ReflectionClass($className);
|
||||
$staticProperties[$className] = [];
|
||||
foreach($reflection->getProperties() as $property){
|
||||
if(!$property->isStatic() or $property->getDeclaringClass()->getName() !== $className){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!$property->isPublic()){
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
|
||||
$staticCount++;
|
||||
$this->continueDump($property->getValue(), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
|
||||
if(count($staticProperties[$className]) === 0){
|
||||
unset($staticProperties[$className]);
|
||||
}
|
||||
}
|
||||
|
||||
echo "[Dump] Wrote $staticCount static properties\n";
|
||||
|
||||
$this->continueDump($this->server, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
|
||||
do{
|
||||
@ -243,6 +273,11 @@ class MemoryManager{
|
||||
$continue = true;
|
||||
|
||||
$className = get_class($object);
|
||||
if(!isset($instanceCounts[$className])){
|
||||
$instanceCounts[$className] = 1;
|
||||
}else{
|
||||
$instanceCounts[$className]++;
|
||||
}
|
||||
|
||||
$objects[$hash] = true;
|
||||
|
||||
@ -273,33 +308,23 @@ class MemoryManager{
|
||||
}
|
||||
|
||||
fwrite($obData, "$hash@$className: " . json_encode($info, JSON_UNESCAPED_SLASHES) . "\n");
|
||||
|
||||
if(!isset($objects["staticProperties"][$className])){
|
||||
$staticProperties[$className] = [];
|
||||
foreach($reflection->getProperties() as $property){
|
||||
if(!$property->isStatic() or $property->getDeclaringClass()->getName() !== $className){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!$property->isPublic()){
|
||||
$property->setAccessible(true);
|
||||
}
|
||||
$this->continueDump($property->getValue($object), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "[Dump] Wrote " . count($objects) . " objects\n";
|
||||
}while($continue);
|
||||
|
||||
|
||||
fclose($obData);
|
||||
|
||||
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
file_put_contents($outputFolder . "/serverEntry.js", json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
file_put_contents($outputFolder . "/referenceCounts.js", json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
|
||||
arsort($instanceCounts, SORT_NUMERIC);
|
||||
file_put_contents($outputFolder . "/instanceCounts.js", json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
|
||||
|
||||
echo "[Dump] Finished!\n";
|
||||
|
||||
ini_set('memory_limit', $hardLimit);
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\metadata\Metadatable;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\block\Air;
|
||||
@ -112,9 +114,11 @@ use pocketmine\network\mcpe\protocol\AddPlayerPacket;
|
||||
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
|
||||
use pocketmine\network\mcpe\protocol\AnimatePacket;
|
||||
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
|
||||
use pocketmine\network\mcpe\protocol\BatchPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\BossEventPacket;
|
||||
use pocketmine\network\mcpe\protocol\ChangeDimensionPacket;
|
||||
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
|
||||
use pocketmine\network\mcpe\protocol\ClientboundMapItemDataPacket;
|
||||
@ -148,7 +152,7 @@ use pocketmine\network\mcpe\protocol\MobEquipmentPacket;
|
||||
use pocketmine\network\mcpe\protocol\MoveEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerActionPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerFallPacket;
|
||||
use pocketmine\network\mcpe\protocol\EntityFallPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerInputPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerListPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlaySoundPacket;
|
||||
@ -184,7 +188,6 @@ use pocketmine\network\mcpe\protocol\StopSoundPacket;
|
||||
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
|
||||
use pocketmine\network\mcpe\protocol\TextPacket;
|
||||
use pocketmine\network\mcpe\protocol\TransferPacket;
|
||||
use pocketmine\network\mcpe\protocol\UnknownPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
|
||||
use pocketmine\network\mcpe\protocol\UpdateTradePacket;
|
||||
@ -287,6 +290,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
protected $stepHeight = 0.6;
|
||||
|
||||
protected $baseOffset = 1.62;
|
||||
|
||||
public $usedChunks = [];
|
||||
protected $chunkLoadCount = 0;
|
||||
protected $loadQueue = [];
|
||||
@ -763,10 +768,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
}
|
||||
|
||||
$this->usedChunks = [];
|
||||
$pk = new SetTimePacket();
|
||||
$pk->time = $this->level->getTime();
|
||||
$pk->started = $this->level->stopTime == false;
|
||||
$this->dataPacket($pk);
|
||||
$this->level->sendTime($this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -806,7 +808,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return $this->spawnPosition instanceof WeakPosition and $this->spawnPosition->isValid();
|
||||
}
|
||||
|
||||
public function sendChunk($x, $z, $payload){
|
||||
public function sendChunk(int $x, int $z, BatchPacket $payload){
|
||||
if($this->connected === false){
|
||||
return;
|
||||
}
|
||||
@ -814,15 +816,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$this->usedChunks[Level::chunkHash($x, $z)] = true;
|
||||
$this->chunkLoadCount++;
|
||||
|
||||
if($payload instanceof DataPacket){
|
||||
$this->dataPacket($payload);
|
||||
}else{
|
||||
$pk = new FullChunkDataPacket();
|
||||
$pk->chunkX = $x;
|
||||
$pk->chunkZ = $z;
|
||||
$pk->data = $payload;
|
||||
$this->batchDataPacket($pk);
|
||||
}
|
||||
$this->dataPacket($payload);
|
||||
|
||||
if($this->spawned){
|
||||
foreach($this->level->getChunkEntities($x, $z) as $entity){
|
||||
@ -849,6 +843,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$X = null;
|
||||
$Z = null;
|
||||
Level::getXZ($index, $X, $Z);
|
||||
assert(is_int($X) and is_int($Z));
|
||||
|
||||
++$count;
|
||||
|
||||
@ -879,27 +874,19 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
$this->sendSettings();
|
||||
$this->sendPotionEffects($this);
|
||||
|
||||
$this->sendData($this);
|
||||
$this->inventory->sendContents($this);
|
||||
$this->inventory->sendArmorContents($this);
|
||||
$this->inventory->sendHeldItem($this);
|
||||
|
||||
$pk = new SetTimePacket();
|
||||
$pk->time = $this->level->getTime();
|
||||
$pk->started = $this->level->stopTime == false;
|
||||
$this->dataPacket($pk);
|
||||
|
||||
$pos = $this->level->getSafeSpawn($this);
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerRespawnEvent($this, $pos));
|
||||
|
||||
$pos = $ev->getRespawnPosition();
|
||||
|
||||
$pk = new RespawnPacket();
|
||||
$pk->x = $pos->x;
|
||||
$pk->y = $pos->y;
|
||||
$pk->z = $pos->z;
|
||||
$this->dataPacket($pk);
|
||||
$this->sendRespawnPacket($pos);
|
||||
|
||||
$this->sendPlayStatus(PlayStatusPacket::PLAYER_SPAWN);
|
||||
|
||||
@ -915,7 +902,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$this->getDisplayName()
|
||||
])
|
||||
));
|
||||
if(strlen(trim($ev->getJoinMessage())) > 0){
|
||||
if(strlen(trim((string) $ev->getJoinMessage())) > 0){
|
||||
$this->server->broadcastMessage($ev->getJoinMessage());
|
||||
}
|
||||
|
||||
@ -934,22 +921,25 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
$this->spawnToAll();
|
||||
|
||||
if($this->server->getUpdater()->hasUpdate() and $this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE)){
|
||||
if($this->server->getUpdater()->hasUpdate() and $this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE) and $this->server->getProperty("auto-updater.on-update.warn-ops", true)){
|
||||
$this->server->getUpdater()->showPlayerUpdate($this);
|
||||
}
|
||||
|
||||
if($this->getHealth() <= 0){
|
||||
$pk = new RespawnPacket();
|
||||
$pos = $this->getSpawn();
|
||||
$pk->x = $pos->x;
|
||||
$pk->y = $pos->y;
|
||||
$pk->z = $pos->z;
|
||||
$this->dataPacket($pk);
|
||||
$this->sendRespawnPacket($this->getSpawn());
|
||||
}
|
||||
|
||||
$this->joined = true;
|
||||
}
|
||||
|
||||
protected function sendRespawnPacket(Vector3 $pos){
|
||||
$pk = new RespawnPacket();
|
||||
$pk->x = $pos->x;
|
||||
$pk->y = $pos->y + $this->baseOffset;
|
||||
$pk->z = $pos->z;
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
|
||||
protected function orderChunks(){
|
||||
if($this->connected === false or $this->viewDistance === -1){
|
||||
return false;
|
||||
@ -1195,6 +1185,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$pk->x = (int) $this->spawnPosition->x;
|
||||
$pk->y = (int) $this->spawnPosition->y;
|
||||
$pk->z = (int) $this->spawnPosition->z;
|
||||
$pk->spawnType = SetSpawnPositionPacket::TYPE_PLAYER_SPAWN;
|
||||
$pk->spawnForced = false;
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
|
||||
@ -1209,7 +1201,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$this->level->sleepTicks = 0;
|
||||
|
||||
$pk = new AnimatePacket();
|
||||
$pk->eid = $this->id;
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->action = 3; //Wake up
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
@ -1248,6 +1240,26 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return $this->gamemode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* Returns a client-friendly gamemode of the specified real gamemode
|
||||
* This function takes care of handling gamemodes known to MCPE (as of 1.1.0.3, that includes Survival, Creative and Adventure)
|
||||
*
|
||||
* TODO: remove this when Spectator Mode gets added properly to MCPE
|
||||
*
|
||||
* @param int $gamemode
|
||||
* @return int
|
||||
*/
|
||||
public static function getClientFriendlyGamemode(int $gamemode) : int{
|
||||
$gamemode &= 0x03;
|
||||
if($gamemode === Player::SPECTATOR){
|
||||
return Player::CREATIVE;
|
||||
}
|
||||
|
||||
return $gamemode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the gamemode, and if needed, kicks the Player.
|
||||
*
|
||||
@ -1261,13 +1273,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerGameModeChangeEvent($this, (int) $gm));
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerGameModeChangeEvent($this, $gm));
|
||||
if($ev->isCancelled()){
|
||||
if($client){ //gamemode change by client in the GUI
|
||||
$pk = new SetPlayerGameTypePacket();
|
||||
$pk->gamemode = $this->gamemode & 0x01;
|
||||
$this->dataPacket($pk);
|
||||
$this->sendSettings();
|
||||
$this->sendGamemode();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1294,9 +1303,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
$this->namedtag->playerGameType = new IntTag("playerGameType", $this->gamemode);
|
||||
if(!$client){ //Gamemode changed by server, do not send for client changes
|
||||
$pk = new SetPlayerGameTypePacket();
|
||||
$pk->gamemode = $this->gamemode & 0x01;
|
||||
$this->dataPacket($pk);
|
||||
$this->sendGamemode();
|
||||
}else{
|
||||
Command::broadcastCommandMessage($this, new TranslationContainer("commands.gamemode.success.self", [Server::getGamemodeString($gm)]));
|
||||
}
|
||||
@ -1313,6 +1320,16 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Sends the player's gamemode to the client.
|
||||
*/
|
||||
public function sendGamemode(){
|
||||
$pk = new SetPlayerGameTypePacket();
|
||||
$pk->gamemode = Player::getClientFriendlyGamemode($this->gamemode);
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends all the option flags
|
||||
*/
|
||||
@ -1320,6 +1337,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$pk = new AdventureSettingsPacket();
|
||||
$pk->flags = 0;
|
||||
$pk->worldImmutable = $this->isSpectator();
|
||||
$pk->noPvp = $this->isSpectator();
|
||||
$pk->autoJump = $this->autoJump;
|
||||
$pk->allowFlight = $this->allowFlight;
|
||||
$pk->noClip = $this->isSpectator();
|
||||
@ -1545,7 +1563,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$delta = pow($this->lastX - $to->x, 2) + pow($this->lastY - $to->y, 2) + pow($this->lastZ - $to->z, 2);
|
||||
$deltaAngle = abs($this->lastYaw - $to->yaw) + abs($this->lastPitch - $to->pitch);
|
||||
|
||||
if(!$revert and ($delta > (1 / 16) or $deltaAngle > 10)){
|
||||
if(!$revert and ($delta > 0.0001 or $deltaAngle > 1.0)){
|
||||
|
||||
$isFirst = ($this->lastX === null or $this->lastY === null or $this->lastZ === null);
|
||||
|
||||
@ -1565,10 +1583,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
if($to->distanceSquared($ev->getTo()) > 0.01){ //If plugins modify the destination
|
||||
$this->teleport($ev->getTo());
|
||||
}else{
|
||||
$this->level->addEntityMovement($this->x >> 4, $this->z >> 4, $this->getId(), $this->x, $this->y + $this->getEyeHeight(), $this->z, $this->yaw, $this->pitch, $this->yaw);
|
||||
$this->level->addEntityMovement($this->x >> 4, $this->z >> 4, $this->getId(), $this->x, $this->y + $this->baseOffset, $this->z, $this->yaw, $this->pitch, $this->yaw);
|
||||
|
||||
$distance = $from->distance($to);
|
||||
|
||||
//TODO: check swimming (adds 0.015 exhaustion in MCPE)
|
||||
if($this->isSprinting()){
|
||||
$this->exhaust(0.1 * $distance, PlayerExhaustEvent::CAUSE_SPRINTING);
|
||||
@ -1628,7 +1645,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$entries = $sendAll ? $this->attributeMap->getAll() : $this->attributeMap->needSend();
|
||||
if(count($entries) > 0){
|
||||
$pk = new UpdateAttributesPacket();
|
||||
$pk->entityId = $this->id;
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->entries = $entries;
|
||||
$this->dataPacket($pk);
|
||||
foreach($entries as $entry){
|
||||
@ -1796,7 +1813,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
$this->allowFlight = (bool) ($this->gamemode & 0x01);
|
||||
|
||||
if(($level = $this->server->getLevelByName($this->namedtag["Level"])) === null){
|
||||
if(($level = $this->server->getLevelByName((string) $this->namedtag["Level"])) === null){
|
||||
$this->setLevel($this->server->getDefaultLevel());
|
||||
$this->namedtag["Level"] = $this->level->getName();
|
||||
$this->namedtag["Pos"][0] = $this->level->getSpawnLocation()->x;
|
||||
@ -1813,7 +1830,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$this->achievements[$achievement->getName()] = $achievement->getValue() > 0 ? true : false;
|
||||
}
|
||||
|
||||
$this->namedtag->lastPlayed = new LongTag("lastPlayed", floor(microtime(true) * 1000));
|
||||
$this->namedtag->lastPlayed = new LongTag("lastPlayed", (int) floor(microtime(true) * 1000));
|
||||
if($this->server->getAutoSave()){
|
||||
$this->server->saveOfflinePlayerData($this->username, $this->namedtag, true);
|
||||
}
|
||||
@ -1831,15 +1848,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
protected function completeLoginSequence(){
|
||||
parent::__construct($this->level, $this->namedtag);
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerLoginEvent($this, "Plugin reason"));
|
||||
if($ev->isCancelled()){
|
||||
$this->close($this->getLeaveMessage(), $ev->getKickMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(!$this->hasValidSpawnPosition() and isset($this->namedtag->SpawnLevel) and ($level = $this->server->getLevelByName($this->namedtag["SpawnLevel"])) instanceof Level){
|
||||
$this->spawnPosition = new WeakPosition($this->namedtag["SpawnX"], $this->namedtag["SpawnY"], $this->namedtag["SpawnZ"], $level);
|
||||
if(!$this->hasValidSpawnPosition()){
|
||||
if(isset($this->namedtag->SpawnLevel) and ($level = $this->server->getLevelByName((string) $this->namedtag["SpawnLevel"])) instanceof Level){
|
||||
$this->spawnPosition = new WeakPosition($this->namedtag["SpawnX"], $this->namedtag["SpawnY"], $this->namedtag["SpawnZ"], $level);
|
||||
}else{
|
||||
$this->spawnPosition = WeakPosition::fromObject($this->level->getSafeSpawn());
|
||||
}
|
||||
}
|
||||
|
||||
$spawnPosition = $this->getSpawn();
|
||||
@ -1847,34 +1862,42 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$pk = new StartGamePacket();
|
||||
$pk->entityUniqueId = $this->id;
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->playerGamemode = Player::getClientFriendlyGamemode($this->gamemode);
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
$pk->z = $this->z;
|
||||
$pk->pitch = $this->pitch;
|
||||
$pk->yaw = $this->yaw;
|
||||
$pk->seed = -1;
|
||||
$pk->dimension = 0; //TODO: implement this properly
|
||||
$pk->gamemode = $this->gamemode & 0x01;
|
||||
$pk->worldGamemode = Player::getClientFriendlyGamemode($this->server->getGamemode());
|
||||
$pk->difficulty = $this->server->getDifficulty();
|
||||
$pk->spawnX = $spawnPosition->getFloorX();
|
||||
$pk->spawnY = $spawnPosition->getFloorY();
|
||||
$pk->spawnZ = $spawnPosition->getFloorZ();
|
||||
$pk->hasBeenLoadedInCreative = 1;
|
||||
$pk->hasAchievementsDisabled = true;
|
||||
$pk->dayCycleStopTime = -1; //TODO: implement this properly
|
||||
$pk->eduMode = 0;
|
||||
$pk->eduMode = false;
|
||||
$pk->rainLevel = 0; //TODO: implement these properly
|
||||
$pk->lightningLevel = 0;
|
||||
$pk->commandsEnabled = 1;
|
||||
$pk->commandsEnabled = true;
|
||||
$pk->levelId = "";
|
||||
$pk->worldName = $this->server->getMotd();
|
||||
$this->dataPacket($pk);
|
||||
|
||||
$pk = new SetTimePacket();
|
||||
$pk->time = $this->level->getTime();
|
||||
$pk->started = $this->level->stopTime == false;
|
||||
$this->dataPacket($pk);
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerLoginEvent($this, "Plugin reason"));
|
||||
if($ev->isCancelled()){
|
||||
$this->close($this->getLeaveMessage(), $ev->getKickMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->level->sendTime($this);
|
||||
|
||||
$this->sendAttributes(true);
|
||||
$this->setNameTagVisible(true);
|
||||
$this->setNameTagAlwaysVisible(true);
|
||||
$this->setCanClimb(true);
|
||||
|
||||
$this->server->getLogger()->info($this->getServer()->getLanguage()->translateString("pocketmine.player.logIn", [
|
||||
TextFormat::AQUA . $this->username . TextFormat::WHITE,
|
||||
@ -1909,15 +1932,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->username = TextFormat::clean($packet->username);
|
||||
$this->displayName = $this->username;
|
||||
$this->iusername = strtolower($this->username);
|
||||
$this->setDataProperty(self::DATA_NAMETAG, self::DATA_TYPE_STRING, $this->username, false);
|
||||
|
||||
if(count($this->server->getOnlinePlayers()) >= $this->server->getMaxPlayers() and $this->kick("disconnectionScreen.serverFull", false)){
|
||||
return true;
|
||||
}
|
||||
|
||||
if($packet->protocol !== ProtocolInfo::CURRENT_PROTOCOL){
|
||||
if($packet->protocol < ProtocolInfo::CURRENT_PROTOCOL){
|
||||
$message = "disconnectionScreen.outdatedClient";
|
||||
@ -1931,6 +1945,15 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->username = TextFormat::clean($packet->username);
|
||||
$this->displayName = $this->username;
|
||||
$this->iusername = strtolower($this->username);
|
||||
$this->setDataProperty(self::DATA_NAMETAG, self::DATA_TYPE_STRING, $this->username, false);
|
||||
|
||||
if(count($this->server->getOnlinePlayers()) >= $this->server->getMaxPlayers() and $this->kick("disconnectionScreen.serverFull", false)){
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->randomClientId = $packet->clientId;
|
||||
|
||||
$this->uuid = UUID::fromString($packet->clientUUID);
|
||||
@ -2016,7 +2039,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$pk = new ResourcePackDataInfoPacket();
|
||||
$pk->packId = $pack->getPackId();
|
||||
$pk->maxChunkSize = 1048576; //1MB
|
||||
$pk->chunkCount = $pack->getPackSize() / $pk->maxChunkSize;
|
||||
$pk->chunkCount = (int) ceil($pack->getPackSize() / $pk->maxChunkSize);
|
||||
$pk->compressedPackSize = $pack->getPackSize();
|
||||
$pk->sha256 = $pack->getSha256();
|
||||
$this->dataPacket($pk);
|
||||
@ -2119,7 +2142,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
}
|
||||
|
||||
public function handleMovePlayer(MovePlayerPacket $packet) : bool{
|
||||
$newPos = new Vector3($packet->x, $packet->y - $this->getEyeHeight(), $packet->z);
|
||||
$newPos = new Vector3($packet->x, $packet->y - $this->baseOffset, $packet->z);
|
||||
|
||||
$revert = false;
|
||||
if(!$this->isAlive() or $this->spawned !== true){
|
||||
@ -2262,7 +2285,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
if($packet->inventorySlot === 255){
|
||||
$packet->inventorySlot = -1; //Cleared slot
|
||||
}else{
|
||||
if($packet->inventorySlot < 9){
|
||||
$this->server->getLogger()->debug("Tried to equip a slot that does not exist (index " . $packet->inventorySlot . ")");
|
||||
$this->inventory->sendContents($this);
|
||||
return false;
|
||||
}
|
||||
$packet->inventorySlot -= 9; //Get real inventory slot
|
||||
|
||||
$item = $this->inventory->getItem($packet->inventorySlot);
|
||||
|
||||
if(!$item->equals($packet->item)){
|
||||
@ -2410,7 +2439,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
case InteractPacket::ACTION_MOUSEOVER:
|
||||
break; //TODO: handle these
|
||||
default:
|
||||
$this->server->getLogger()->debug("Unhandled/unknown interaction type " . $packet->action . "received from ". $this->getName());
|
||||
$this->server->getLogger()->debug("Unhandled/unknown interaction type " . $packet->action . "received from " . $this->getName());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2418,18 +2448,21 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
}
|
||||
|
||||
public function handleBlockPickRequest(BlockPickRequestPacket $packet) : bool{
|
||||
$tile = $this->getLevel()->getTile($this->temporalVector->setComponents($packet->tileX, $packet->tileY, $packet->tileZ));
|
||||
if($tile instanceof Tile){ //TODO: check if the held item matches the target tile
|
||||
$nbt = $tile->getCleanedNBT();
|
||||
if($nbt instanceof CompoundTag){
|
||||
$item = $this->inventory->getItemInHand();
|
||||
$item->setCustomBlockData($nbt);
|
||||
$item->setLore(["+(DATA)"]);
|
||||
$this->inventory->setItemInHand($item);
|
||||
}
|
||||
if($this->isCreative()){
|
||||
$tile = $this->getLevel()->getTile($this->temporalVector->setComponents($packet->tileX, $packet->tileY, $packet->tileZ));
|
||||
if($tile instanceof Tile){ //TODO: check if the held item matches the target tile
|
||||
$nbt = $tile->getCleanedNBT();
|
||||
if($nbt instanceof CompoundTag){
|
||||
$item = $this->inventory->getItemInHand();
|
||||
$item->setCustomBlockData($nbt);
|
||||
$item->setLore(["+(DATA)"]);
|
||||
$this->inventory->setItemInHand($item);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2448,7 +2481,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
if(!$this->canInteract($blockVector->add(0.5, 0.5, 0.5), 13) or $this->isSpectator()){
|
||||
}elseif($this->isCreative()){
|
||||
$item = $this->inventory->getItemInHand();
|
||||
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){
|
||||
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this, true) === true){
|
||||
return true;
|
||||
}
|
||||
}elseif(!$this->inventory->getItemInHand()->equals($packet->item)){
|
||||
@ -2457,7 +2490,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$item = $this->inventory->getItemInHand();
|
||||
$oldItem = clone $item;
|
||||
//TODO: Implement adventure mode checks
|
||||
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this)){
|
||||
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this, true)){
|
||||
if(!$item->equals($oldItem) or $item->getCount() !== $oldItem->getCount()){
|
||||
$this->inventory->setItemInHand($item);
|
||||
$this->inventory->sendHeldItem($this->hasSpawned);
|
||||
@ -2503,17 +2536,17 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
if($item->getId() === Item::SNOWBALL){
|
||||
$nbt = new CompoundTag("", [
|
||||
"Pos" => new ListTag("Pos", [
|
||||
new ListTag("Pos", [
|
||||
new DoubleTag("", $this->x),
|
||||
new DoubleTag("", $this->y + $this->getEyeHeight()),
|
||||
new DoubleTag("", $this->z)
|
||||
]),
|
||||
"Motion" => new ListTag("Motion", [
|
||||
new ListTag("Motion", [
|
||||
new DoubleTag("", $aimPos->x),
|
||||
new DoubleTag("", $aimPos->y),
|
||||
new DoubleTag("", $aimPos->z)
|
||||
]),
|
||||
"Rotation" => new ListTag("Rotation", [
|
||||
new ListTag("Rotation", [
|
||||
new FloatTag("", $this->yaw),
|
||||
new FloatTag("", $this->pitch)
|
||||
]),
|
||||
@ -2551,7 +2584,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return true;
|
||||
}
|
||||
|
||||
$packet->eid = $this->id;
|
||||
$packet->entityRuntimeId = $this->id;
|
||||
$pos = new Vector3($packet->x, $packet->y, $packet->z);
|
||||
|
||||
switch($packet->action){
|
||||
@ -2571,12 +2604,22 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$this->level->setBlock($block, new Air());
|
||||
break;
|
||||
}
|
||||
|
||||
if(!$this->isCreative()){
|
||||
//TODO: improve this to take stuff like swimming, ladders, enchanted tools into account, fix wrong tool break time calculations for bad tools (pmmp/PocketMine-MP#211)
|
||||
$breakTime = ceil($target->getBreakTime($this->inventory->getItemInHand()) * 20);
|
||||
if($breakTime > 0){
|
||||
$this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_START_BREAK, (int) (65535 / $breakTime));
|
||||
}
|
||||
}
|
||||
$this->lastBreak = microtime(true);
|
||||
break;
|
||||
|
||||
/** @noinspection PhpMissingBreakStatementInspection */
|
||||
case PlayerActionPacket::ACTION_ABORT_BREAK:
|
||||
$this->lastBreak = PHP_INT_MAX;
|
||||
break;
|
||||
case PlayerActionPacket::ACTION_STOP_BREAK:
|
||||
$this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_STOP_BREAK);
|
||||
break;
|
||||
case PlayerActionPacket::ACTION_RELEASE_ITEM:
|
||||
if($this->startAction > -1 and $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION)){
|
||||
@ -2588,21 +2631,22 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
}
|
||||
|
||||
$nbt = new CompoundTag("", [
|
||||
"Pos" => new ListTag("Pos", [
|
||||
new ListTag("Pos", [
|
||||
new DoubleTag("", $this->x),
|
||||
new DoubleTag("", $this->y + $this->getEyeHeight()),
|
||||
new DoubleTag("", $this->z)
|
||||
]),
|
||||
"Motion" => new ListTag("Motion", [
|
||||
new ListTag("Motion", [
|
||||
new DoubleTag("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)),
|
||||
new DoubleTag("", -sin($this->pitch / 180 * M_PI)),
|
||||
new DoubleTag("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))
|
||||
]),
|
||||
"Rotation" => new ListTag("Rotation", [
|
||||
new FloatTag("", $this->yaw),
|
||||
new FloatTag("", $this->pitch)
|
||||
new ListTag("Rotation", [
|
||||
//yaw/pitch for arrows taken crosswise, not along the arrow shaft.
|
||||
new FloatTag("", ($this->yaw > 180 ? 360 : 0) - $this->yaw), //arrow yaw must range from -180 to +180
|
||||
new FloatTag("", -$this->pitch)
|
||||
]),
|
||||
"Fire" => new ShortTag("Fire", $this->isOnFire() ? 45 * 60 : 0)
|
||||
new ShortTag("Fire", $this->isOnFire() ? 45 * 60 : 0)
|
||||
]);
|
||||
|
||||
$diff = ($this->server->getTick() - $this->startAction);
|
||||
@ -2651,7 +2695,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
}
|
||||
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->eid = $this->getId();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->event = EntityEventPacket::USE_ITEM;
|
||||
$this->dataPacket($pk);
|
||||
$this->server->broadcastPacket($this->getViewers(), $pk);
|
||||
@ -2691,7 +2735,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$this->setSneaking(false);
|
||||
|
||||
$this->extinguish();
|
||||
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 400, false);
|
||||
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 400);
|
||||
$this->deadTicks = 0;
|
||||
$this->noDamageTicks = 60;
|
||||
|
||||
@ -2753,6 +2797,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
case PlayerActionPacket::ACTION_START_GLIDE:
|
||||
case PlayerActionPacket::ACTION_STOP_GLIDE:
|
||||
break; //TODO
|
||||
case PlayerActionPacket::ACTION_CONTINUE_BREAK:
|
||||
$block = $this->level->getBlock($pos);
|
||||
$this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_PARTICLE_PUNCH_BLOCK, $block->getId() | ($block->getDamage() << 8) | ($packet->face << 16));
|
||||
break;
|
||||
default:
|
||||
$this->server->getLogger()->debug("Unhandled/unknown player action type " . $packet->action . " from " . $this->getName());
|
||||
return false;
|
||||
@ -2764,8 +2812,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handlePlayerFall(PlayerFallPacket $packet) : bool{
|
||||
return false;
|
||||
public function handleEntityFall(EntityFallPacket $packet) : bool{
|
||||
return true; //not used
|
||||
}
|
||||
|
||||
public function handleHurtArmor(HurtArmorPacket $packet) : bool{
|
||||
@ -2803,7 +2851,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
}
|
||||
|
||||
$pk = new AnimatePacket();
|
||||
$pk->eid = $this->getId();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->action = $ev->getAnimationType();
|
||||
$this->server->broadcastPacket($this->getViewers(), $pk);
|
||||
|
||||
@ -3198,11 +3246,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
}
|
||||
|
||||
public function handleSetPlayerGameType(SetPlayerGameTypePacket $packet) : bool{
|
||||
if($packet->gamemode !== ($this->gamemode & 0x01)){
|
||||
//GUI gamemode change, set it back to original for now (only possible through client bug or hack with current allowed client permissions)
|
||||
$pk = new SetPlayerGameTypePacket();
|
||||
$pk->gamemode = $this->gamemode & 0x01;
|
||||
$this->dataPacket($pk);
|
||||
if($packet->gamemode !== $this->gamemode){
|
||||
//Set this back to default. TODO: handle this properly
|
||||
$this->sendGamemode();
|
||||
$this->sendSettings();
|
||||
}
|
||||
return true;
|
||||
@ -3241,7 +3287,14 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
$tile = $this->level->getTile($this->temporalVector->setComponents($packet->x, $packet->y, $packet->z));
|
||||
if($tile instanceof ItemFrame){
|
||||
$ev = new PlayerInteractEvent($this, $this->inventory->getItemInHand(), $tile->getBlock(), 5 - $tile->getBlock()->getDamage(), PlayerInteractEvent::LEFT_CLICK_BLOCK);
|
||||
$this->server->getPluginManager()->callEvent($ev);
|
||||
|
||||
if($this->isSpectator()){
|
||||
$ev->setCancelled();
|
||||
}
|
||||
|
||||
if($ev->isCancelled()){
|
||||
$tile->spawnTo($this);
|
||||
return true;
|
||||
}
|
||||
@ -3264,6 +3317,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleBossEvent(BossEventPacket $packet) : bool{
|
||||
return false; //TODO
|
||||
}
|
||||
|
||||
public function handleShowCredits(ShowCreditsPacket $packet) : bool{
|
||||
return false; //TODO: handle resume
|
||||
}
|
||||
@ -3278,8 +3335,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
}
|
||||
$this->craftingType = 0;
|
||||
$commandText = $packet->command;
|
||||
if($packet->args !== null){
|
||||
foreach($packet->args as $arg){ //command ordering will be an issue
|
||||
if($packet->inputJson !== null){
|
||||
foreach($packet->inputJson as $arg){ //command ordering will be an issue
|
||||
$commandText .= " " . $arg;
|
||||
}
|
||||
}
|
||||
@ -3356,11 +3413,19 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: Remove this hack once InteractPacket spam issue is fixed
|
||||
if($packet->buffer === "\x21\x04\x00"){
|
||||
return;
|
||||
}
|
||||
|
||||
$timings = Timings::getReceiveDataPacketTimings($packet);
|
||||
$timings->startTiming();
|
||||
|
||||
$packet->decode();
|
||||
assert($packet->feof(), "Still " . strlen(substr($packet->buffer, $packet->offset)) . " bytes unread in " . get_class($packet));
|
||||
if(!$packet->feof()){
|
||||
$remains = substr($packet->buffer, $packet->offset);
|
||||
$this->server->getLogger()->debug("Still " . strlen($remains) . " bytes unread in " . $packet->getName() . ": 0x" . bin2hex($remains));
|
||||
}
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev = new DataPacketReceiveEvent($this, $packet));
|
||||
if(!$ev->isCancelled() and !$packet->handle($this)){
|
||||
@ -3439,11 +3504,20 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
public function addTitle(string $title, string $subtitle = "", int $fadeIn = -1, int $stay = -1, int $fadeOut = -1){
|
||||
$this->setTitleDuration($fadeIn, $stay, $fadeOut);
|
||||
if($subtitle !== ""){
|
||||
$this->sendTitleText($subtitle, SetTitlePacket::TYPE_SET_SUBTITLE);
|
||||
$this->addSubTitle($subtitle);
|
||||
}
|
||||
$this->sendTitleText($title, SetTitlePacket::TYPE_SET_TITLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the subtitle message, without sending a title.
|
||||
*
|
||||
* @param string $subtitle
|
||||
*/
|
||||
public function addSubTitle(string $subtitle){
|
||||
$this->sendTitleText($subtitle, SetTitlePacket::TYPE_SET_SUBTITLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds small text to the user's screen.
|
||||
*
|
||||
@ -3462,6 +3536,15 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the title duration settings.
|
||||
*/
|
||||
public function resetTitles(){
|
||||
$pk = new SetTitlePacket();
|
||||
$pk->type = SetTitlePacket::TYPE_RESET_TITLE;
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the title duration.
|
||||
*
|
||||
@ -3496,7 +3579,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
/**
|
||||
* Sends a direct chat message to a player
|
||||
*
|
||||
* @param string|TextContainer $message
|
||||
* @param TextContainer|string $message
|
||||
*/
|
||||
public function sendMessage($message){
|
||||
if($message instanceof TextContainer){
|
||||
@ -3566,84 +3649,91 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
*/
|
||||
final public function close($message = "", $reason = "generic reason", $notify = true){
|
||||
if($this->connected and !$this->closed){
|
||||
if($notify and strlen((string) $reason) > 0){
|
||||
$pk = new DisconnectPacket();
|
||||
$pk->message = $reason;
|
||||
$this->directDataPacket($pk);
|
||||
}
|
||||
|
||||
$this->connected = false;
|
||||
|
||||
$this->server->getPluginManager()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this);
|
||||
$this->server->getPluginManager()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this);
|
||||
|
||||
if($this->joined){
|
||||
//TODO: add events for player data saving
|
||||
$this->save();
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerQuitEvent($this, $message));
|
||||
if($ev->getQuitMessage() != ""){
|
||||
$this->server->broadcastMessage($ev->getQuitMessage());
|
||||
try{
|
||||
if($notify and strlen((string) $reason) > 0){
|
||||
$pk = new DisconnectPacket();
|
||||
$pk->message = $reason;
|
||||
$this->directDataPacket($pk);
|
||||
}
|
||||
}
|
||||
$this->joined = false;
|
||||
|
||||
if($this->isValid()){
|
||||
foreach($this->usedChunks as $index => $d){
|
||||
Level::getXZ($index, $chunkX, $chunkZ);
|
||||
$this->level->unregisterChunkLoader($this, $chunkX, $chunkZ);
|
||||
foreach($this->level->getChunkEntities($chunkX, $chunkZ) as $entity){
|
||||
$entity->despawnFrom($this);
|
||||
$this->connected = false;
|
||||
|
||||
$this->server->getPluginManager()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this);
|
||||
$this->server->getPluginManager()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this);
|
||||
|
||||
if($this->joined){
|
||||
try{
|
||||
$this->save();
|
||||
}catch(\Throwable $e){
|
||||
$this->server->getLogger()->critical("Failed to save player data for " . $this->getName());
|
||||
$this->server->getLogger()->logException($e);
|
||||
}
|
||||
|
||||
$this->server->getPluginManager()->callEvent($ev = new PlayerQuitEvent($this, $message));
|
||||
if($ev->getQuitMessage() != ""){
|
||||
$this->server->broadcastMessage($ev->getQuitMessage());
|
||||
}
|
||||
unset($this->usedChunks[$index]);
|
||||
}
|
||||
}
|
||||
$this->usedChunks = [];
|
||||
$this->loadQueue = [];
|
||||
$this->joined = false;
|
||||
|
||||
foreach($this->server->getOnlinePlayers() as $player){
|
||||
if(!$player->canSee($this)){
|
||||
$player->showPlayer($this);
|
||||
if($this->isValid()){
|
||||
foreach($this->usedChunks as $index => $d){
|
||||
Level::getXZ($index, $chunkX, $chunkZ);
|
||||
$this->level->unregisterChunkLoader($this, $chunkX, $chunkZ);
|
||||
foreach($this->level->getChunkEntities($chunkX, $chunkZ) as $entity){
|
||||
$entity->despawnFrom($this);
|
||||
}
|
||||
unset($this->usedChunks[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->hiddenPlayers = [];
|
||||
$this->usedChunks = [];
|
||||
$this->loadQueue = [];
|
||||
|
||||
foreach($this->windowIndex as $window){
|
||||
$this->removeWindow($window);
|
||||
}
|
||||
$this->windows = null;
|
||||
$this->windowIndex = [];
|
||||
foreach($this->server->getOnlinePlayers() as $player){
|
||||
if(!$player->canSee($this)){
|
||||
$player->showPlayer($this);
|
||||
}
|
||||
}
|
||||
$this->hiddenPlayers = [];
|
||||
|
||||
parent::close();
|
||||
$this->spawned = false;
|
||||
foreach($this->windowIndex as $window){
|
||||
$this->removeWindow($window);
|
||||
}
|
||||
$this->windows = null;
|
||||
$this->windowIndex = [];
|
||||
|
||||
$this->interface->close($this, $notify ? $reason : "");
|
||||
parent::close();
|
||||
$this->spawned = false;
|
||||
|
||||
if($this->loggedIn){
|
||||
$this->interface->close($this, $notify ? $reason : "");
|
||||
|
||||
$this->loggedIn = false;
|
||||
|
||||
$this->server->getLogger()->info($this->getServer()->getLanguage()->translateString("pocketmine.player.logOut", [
|
||||
TextFormat::AQUA . $this->getName() . TextFormat::WHITE,
|
||||
$this->ip,
|
||||
$this->port,
|
||||
$this->getServer()->getLanguage()->translateString($reason)
|
||||
]));
|
||||
|
||||
$this->spawnPosition = null;
|
||||
|
||||
if($this->perm !== null){
|
||||
$this->perm->clearPermissions();
|
||||
$this->perm = null;
|
||||
}
|
||||
|
||||
if($this->inventory !== null){
|
||||
$this->inventory = null;
|
||||
$this->currentTransaction = null;
|
||||
}
|
||||
|
||||
}catch(\Throwable $e){
|
||||
$this->server->getLogger()->logException($e);
|
||||
}finally{
|
||||
$this->server->removeOnlinePlayer($this);
|
||||
$this->server->removePlayer($this);
|
||||
}
|
||||
$this->loggedIn = false;
|
||||
|
||||
$this->server->getLogger()->info($this->getServer()->getLanguage()->translateString("pocketmine.player.logOut", [
|
||||
TextFormat::AQUA . $this->getName() . TextFormat::WHITE,
|
||||
$this->ip,
|
||||
$this->port,
|
||||
$this->getServer()->getLanguage()->translateString($reason)
|
||||
]));
|
||||
|
||||
$this->spawnPosition = null;
|
||||
|
||||
if($this->perm !== null){
|
||||
$this->perm->clearPermissions();
|
||||
$this->perm = null;
|
||||
}
|
||||
|
||||
if($this->inventory !== null){
|
||||
$this->inventory = null;
|
||||
$this->currentTransaction = null;
|
||||
}
|
||||
|
||||
$this->server->removePlayer($this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3668,10 +3758,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
}
|
||||
|
||||
if($this->hasValidSpawnPosition()){
|
||||
$this->namedtag["SpawnLevel"] = $this->spawnPosition->getLevel()->getFolderName();
|
||||
$this->namedtag["SpawnX"] = (int) $this->spawnPosition->x;
|
||||
$this->namedtag["SpawnY"] = (int) $this->spawnPosition->y;
|
||||
$this->namedtag["SpawnZ"] = (int) $this->spawnPosition->z;
|
||||
$this->namedtag->SpawnLevel = new StringTag("SpawnLevel", $this->spawnPosition->getLevel()->getFolderName());
|
||||
$this->namedtag->SpawnX = new IntTag("SpawnX", (int) $this->spawnPosition->x);
|
||||
$this->namedtag->SpawnY = new IntTag("SpawnY", (int) $this->spawnPosition->y);
|
||||
$this->namedtag->SpawnZ = new IntTag("SpawnZ", (int) $this->spawnPosition->z);
|
||||
}
|
||||
|
||||
foreach($this->achievements as $achievement => $status){
|
||||
@ -3679,7 +3769,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
}
|
||||
|
||||
$this->namedtag["playerGameType"] = $this->gamemode;
|
||||
$this->namedtag["lastPlayed"] = new LongTag("lastPlayed", floor(microtime(true) * 1000));
|
||||
$this->namedtag["lastPlayed"] = (int) floor(microtime(true) * 1000);
|
||||
|
||||
if($this->username != "" and $this->namedtag instanceof CompoundTag){
|
||||
$this->server->saveOfflinePlayerData($this->username, $this->namedtag, $async);
|
||||
@ -3709,12 +3799,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
parent::kill();
|
||||
|
||||
$pk = new RespawnPacket();
|
||||
$pos = $this->getSpawn();
|
||||
$pk->x = $pos->x;
|
||||
$pk->y = $pos->y;
|
||||
$pk->z = $pos->z;
|
||||
$this->dataPacket($pk);
|
||||
$this->sendRespawnPacket($this->getSpawn());
|
||||
}
|
||||
|
||||
protected function callDeathEvent(){
|
||||
@ -3870,7 +3955,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return;
|
||||
}elseif($this->getLastDamageCause() === $source and $this->spawned){
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->eid = $this->id;
|
||||
$pk->entityRuntimeId = $this->id;
|
||||
$pk->event = EntityEventPacket::HURT_ANIMATION;
|
||||
$this->dataPacket($pk);
|
||||
|
||||
@ -3885,9 +3970,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$pitch = $pitch === null ? $this->pitch : $pitch;
|
||||
|
||||
$pk = new MovePlayerPacket();
|
||||
$pk->eid = $this->getId();
|
||||
$pk->entityRuntimeId = $this->getId();
|
||||
$pk->x = $pos->x;
|
||||
$pk->y = $pos->y + $this->getEyeHeight();
|
||||
$pk->y = $pos->y + $this->baseOffset;
|
||||
$pk->z = $pos->z;
|
||||
$pk->bodyYaw = $yaw;
|
||||
$pk->pitch = $pitch;
|
||||
@ -3952,6 +4037,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
}
|
||||
|
||||
$this->sendPosition($this, null, null, MovePlayerPacket::MODE_RESET);
|
||||
//This only needs to be sent to players who could see us before the teleport.
|
||||
$this->sendPosition($this, null, null, MovePlayerPacket::MODE_RESET, $this->getViewers());
|
||||
|
||||
$this->spawnToAll();
|
||||
$this->forceMovement = $this->teleportPosition;
|
||||
$this->teleportPosition = null;
|
||||
|
@ -19,7 +19,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace {
|
||||
const INT32_MIN = -0x80000000;
|
||||
const INT32_MAX = 0x7fffffff;
|
||||
|
||||
function safe_var_dump(){
|
||||
static $cnt = 0;
|
||||
foreach(func_get_args() as $var){
|
||||
@ -74,7 +79,7 @@ namespace pocketmine {
|
||||
use raklib\RakLib;
|
||||
|
||||
const VERSION = "1.6.2dev";
|
||||
const API_VERSION = "3.0.0-ALPHA5";
|
||||
const API_VERSION = "3.0.0-ALPHA6";
|
||||
const CODENAME = "Unleashed";
|
||||
|
||||
/*
|
||||
@ -84,12 +89,6 @@ namespace pocketmine {
|
||||
* 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{
|
||||
@define('pocketmine\PATH', \getcwd() . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
if(version_compare("7.0", PHP_VERSION) > 0){
|
||||
echo "[CRITICAL] You must use PHP >= 7.0" . PHP_EOL;
|
||||
echo "[CRITICAL] Please use the installer provided on the homepage." . PHP_EOL;
|
||||
@ -102,6 +101,28 @@ namespace pocketmine {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
error_reporting(-1);
|
||||
|
||||
set_error_handler(function($severity, $message, $file, $line){
|
||||
if((error_reporting() & $severity)){
|
||||
throw new \ErrorException($message, 0, $severity, $file, $line);
|
||||
}else{ //stfu operator
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if(!extension_loaded("phar")){
|
||||
echo "[CRITICAL] Unable to find the Phar extension." . PHP_EOL;
|
||||
echo "[CRITICAL] Please use the installer provided on the homepage." . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(\Phar::running(true) !== ""){
|
||||
define('pocketmine\PATH', \Phar::running(true) . "/");
|
||||
}else{
|
||||
define('pocketmine\PATH', realpath(getcwd()) . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
if(!class_exists("ClassLoader", false)){
|
||||
if(!is_file(\pocketmine\PATH . "src/spl/ClassLoader.php")){
|
||||
echo "[CRITICAL] Unable to find the PocketMine-SPL library." . PHP_EOL;
|
||||
@ -128,13 +149,12 @@ namespace pocketmine {
|
||||
|
||||
set_time_limit(0); //Who set it to 30 seconds?!?!
|
||||
|
||||
error_reporting(-1);
|
||||
ini_set("allow_url_fopen", 1);
|
||||
ini_set("display_errors", 1);
|
||||
ini_set("display_startup_errors", 1);
|
||||
ini_set("allow_url_fopen", '1');
|
||||
ini_set("display_errors", '1');
|
||||
ini_set("display_startup_errors", '1');
|
||||
ini_set("default_charset", "utf-8");
|
||||
|
||||
ini_set("memory_limit", -1);
|
||||
ini_set("memory_limit", '-1');
|
||||
define('pocketmine\START_TIME', microtime(true));
|
||||
|
||||
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-profiler"]);
|
||||
@ -153,7 +173,7 @@ namespace pocketmine {
|
||||
//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);
|
||||
$logger = new MainLogger(\pocketmine\DATA . "server.log");
|
||||
|
||||
if(!ini_get("date.timezone")){
|
||||
if(($timezone = detect_system_timezone()) and date_default_timezone_set($timezone)){
|
||||
@ -227,7 +247,6 @@ namespace pocketmine {
|
||||
}
|
||||
|
||||
return parse_offset($offset);
|
||||
break;
|
||||
case 'linux':
|
||||
// Ubuntu / Debian.
|
||||
if(file_exists('/etc/timezone')){
|
||||
@ -254,7 +273,6 @@ namespace pocketmine {
|
||||
}
|
||||
|
||||
return parse_offset($offset);
|
||||
break;
|
||||
case 'mac':
|
||||
if(is_link('/etc/localtime')){
|
||||
$filename = readlink('/etc/localtime');
|
||||
@ -265,10 +283,8 @@ namespace pocketmine {
|
||||
}
|
||||
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,7 +393,7 @@ namespace pocketmine {
|
||||
$args = $trace[$i]["params"];
|
||||
}
|
||||
foreach($args as $name => $value){
|
||||
$params .= (is_object($value) ? get_class($value) . " " . (method_exists($value, "__toString") ? $value->__toString() : "object") : gettype($value) . " " . (is_array($value) ? "Array()" : Utils::printable(@strval($value)))) . ", ";
|
||||
$params .= (is_object($value) ? get_class($value) . " object" : gettype($value) . " " . (is_array($value) ? "Array()" : Utils::printable(@strval($value)))) . ", ";
|
||||
}
|
||||
}
|
||||
$messages[] = "#$j " . (isset($trace[$i]["file"]) ? cleanPath($trace[$i]["file"]) : "") . "(" . (isset($trace[$i]["line"]) ? $trace[$i]["line"] : "") . "): " . (isset($trace[$i]["class"]) ? $trace[$i]["class"] . (($trace[$i]["type"] === "dynamic" or $trace[$i]["type"] === "->") ? "->" : "::") : "") . $trace[$i]["function"] . "(" . Utils::printable(substr($params, 0, -2)) . ")";
|
||||
@ -387,139 +403,136 @@ namespace pocketmine {
|
||||
}
|
||||
|
||||
function cleanPath($path){
|
||||
return rtrim(str_replace(["\\", ".php", "phar://", rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), "/"), rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH), "/")], ["/", "", "", "", ""], $path), "/");
|
||||
return str_replace(["\\", ".php", "phar://", str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH)], ["/", "", "", "", ""], $path);
|
||||
}
|
||||
|
||||
$errors = 0;
|
||||
$exitCode = 0;
|
||||
|
||||
if(php_sapi_name() !== "cli"){
|
||||
$logger->critical("You must run PocketMine-MP using the CLI.");
|
||||
++$errors;
|
||||
}
|
||||
do{
|
||||
$errors = 0;
|
||||
|
||||
$pthreads_version = phpversion("pthreads");
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "3.1.5") < 0){
|
||||
$logger->critical("pthreads >= 3.1.5 is required, while you have $pthreads_version.");
|
||||
++$errors;
|
||||
}
|
||||
if(PHP_INT_SIZE < 8){
|
||||
$logger->critical("Running PocketMine-MP with 32-bit systems/PHP is no longer supported. Please upgrade to a 64-bit system or use a 64-bit PHP binary.");
|
||||
$exitCode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(extension_loaded("pocketmine")){
|
||||
if(version_compare(phpversion("pocketmine"), "0.0.1") < 0){
|
||||
$logger->critical("You have the native PocketMine extension, but your version is lower than 0.0.1.");
|
||||
++$errors;
|
||||
}elseif(version_compare(phpversion("pocketmine"), "0.0.4") > 0){
|
||||
$logger->critical("You have the native PocketMine extension, but your version is higher than 0.0.4.");
|
||||
if(php_sapi_name() !== "cli"){
|
||||
$logger->critical("You must run PocketMine-MP using the CLI.");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning("
|
||||
|
||||
|
||||
You are running PocketMine with xdebug enabled. This has a major impact on performance.
|
||||
|
||||
");
|
||||
}
|
||||
|
||||
$extensions = [
|
||||
"curl" => "cURL",
|
||||
"json" => "JSON",
|
||||
"mbstring" => "Multibyte String",
|
||||
"yaml" => "YAML",
|
||||
"sockets" => "Sockets",
|
||||
"zip" => "Zip",
|
||||
"zlib" => "Zlib"
|
||||
];
|
||||
|
||||
foreach($extensions as $ext => $name){
|
||||
if(!extension_loaded($ext)){
|
||||
$logger->critical("Unable to find the $name ($ext) extension.");
|
||||
$pthreads_version = phpversion("pthreads");
|
||||
if(substr_count($pthreads_version, ".") < 2){
|
||||
$pthreads_version = "0.$pthreads_version";
|
||||
}
|
||||
if(version_compare($pthreads_version, "3.1.5") < 0){
|
||||
$logger->critical("pthreads >= 3.1.5 is required, while you have $pthreads_version.");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
|
||||
if($errors > 0){
|
||||
$logger->critical("Please use the installer provided on the homepage, or recompile PHP again.");
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
exit(1); //Exit with error
|
||||
}
|
||||
|
||||
if(PHP_INT_SIZE < 8){
|
||||
$logger->warning("Running PocketMine-MP with 32-bit systems/PHP is deprecated. Support for 32-bit may be dropped in the future.");
|
||||
}
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
if(file_exists(\pocketmine\PATH . ".git/HEAD")){ //Found Git information!
|
||||
$ref = trim(file_get_contents(\pocketmine\PATH . ".git/HEAD"));
|
||||
if(preg_match('/^[0-9a-f]{40}$/i', $ref)){
|
||||
$gitHash = strtolower($ref);
|
||||
}elseif(substr($ref, 0, 5) === "ref: "){
|
||||
$refFile = \pocketmine\PATH . ".git/" . substr($ref, 5);
|
||||
if(is_file($refFile)){
|
||||
$gitHash = strtolower(trim(file_get_contents($refFile)));
|
||||
if(extension_loaded("pocketmine")){
|
||||
if(version_compare(phpversion("pocketmine"), "0.0.1") < 0){
|
||||
$logger->critical("You have the native PocketMine extension, but your version is lower than 0.0.1.");
|
||||
++$errors;
|
||||
}elseif(version_compare(phpversion("pocketmine"), "0.0.4") > 0){
|
||||
$logger->critical("You have the native PocketMine extension, but your version is higher than 0.0.4.");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
|
||||
@define("ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? Binary::BIG_ENDIAN : Binary::LITTLE_ENDIAN));
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
|
||||
|
||||
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||
$installer = new SetupWizard();
|
||||
if(!$installer->run()){
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
exit(-1);
|
||||
if(extension_loaded("xdebug")){
|
||||
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running PocketMine with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
$extensions = [
|
||||
"curl" => "cURL",
|
||||
"json" => "JSON",
|
||||
"mbstring" => "Multibyte String",
|
||||
"yaml" => "YAML",
|
||||
"sockets" => "Sockets",
|
||||
"zip" => "Zip",
|
||||
"zlib" => "Zlib"
|
||||
];
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged PocketMine-MP installation detected, do not use on production.");
|
||||
}
|
||||
|
||||
ThreadManager::init();
|
||||
new Server($autoloader, $logger, \pocketmine\PATH, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
|
||||
$logger->info("Stopping other threads");
|
||||
|
||||
$killer = new ServerKiller(8);
|
||||
$killer->start();
|
||||
|
||||
$erroredThreads = 0;
|
||||
foreach(ThreadManager::getInstance()->getAll() as $id => $thread){
|
||||
$logger->debug("Stopping " . $thread->getThreadName() . " thread");
|
||||
try{
|
||||
$thread->quit();
|
||||
$logger->debug($thread->getThreadName() . " thread stopped successfully.");
|
||||
}catch(\ThreadException $e){
|
||||
++$erroredThreads;
|
||||
$logger->debug("Could not stop " . $thread->getThreadName() . " thread: " . $e->getMessage());
|
||||
foreach($extensions as $ext => $name){
|
||||
if(!extension_loaded($ext)){
|
||||
$logger->critical("Unable to find the $name ($ext) extension.");
|
||||
++$errors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($errors > 0){
|
||||
$logger->critical("Please use the installer provided on the homepage, or recompile PHP again.");
|
||||
$exitCode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
$gitHash = str_repeat("00", 20);
|
||||
#ifndef COMPILE
|
||||
if(\Phar::running(true) === ""){
|
||||
if(Utils::execute("git rev-parse HEAD", $out) === 0){
|
||||
$gitHash = trim($out);
|
||||
if(Utils::execute("git diff --quiet") === 1 or Utils::execute("git diff --cached --quiet") === 1){ //Locally-modified
|
||||
$gitHash .= "-dirty";
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
define('pocketmine\GIT_COMMIT', $gitHash);
|
||||
|
||||
|
||||
@define("ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? Binary::BIG_ENDIAN : Binary::LITTLE_ENDIAN));
|
||||
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
|
||||
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
|
||||
|
||||
|
||||
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
|
||||
$installer = new SetupWizard();
|
||||
if(!$installer->run()){
|
||||
$exitCode = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(\Phar::running(true) === ""){
|
||||
$logger->warning("Non-packaged PocketMine-MP installation detected, do not use on production.");
|
||||
}
|
||||
|
||||
ThreadManager::init();
|
||||
new Server($autoloader, $logger, \pocketmine\PATH, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
|
||||
$logger->info("Stopping other threads");
|
||||
|
||||
$killer = new ServerKiller(8);
|
||||
$killer->start();
|
||||
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
|
||||
|
||||
$erroredThreads = 0;
|
||||
foreach(ThreadManager::getInstance()->getAll() as $id => $thread){
|
||||
$logger->debug("Stopping " . $thread->getThreadName() . " thread");
|
||||
try{
|
||||
$thread->quit();
|
||||
$logger->debug($thread->getThreadName() . " thread stopped successfully.");
|
||||
}catch(\ThreadException $e){
|
||||
++$erroredThreads;
|
||||
$logger->debug("Could not stop " . $thread->getThreadName() . " thread: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if($erroredThreads > 0){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
kill(getmypid());
|
||||
}
|
||||
}while(false);
|
||||
|
||||
$logger->shutdown();
|
||||
$logger->join();
|
||||
|
||||
echo Terminal::$FORMAT_RESET . PHP_EOL;
|
||||
|
||||
if($erroredThreads > 0){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
|
||||
}
|
||||
kill(getmypid());
|
||||
}else{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
exit($exitCode);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
/**
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
class ThreadManager extends \Volatile{
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine;
|
||||
|
||||
/**
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class AcaciaWoodStairs extends WoodStairs{
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class ActivatorRail extends Rail{
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -32,8 +34,8 @@ class Air extends Transparent{
|
||||
protected $id = self::AIR;
|
||||
protected $meta = 0;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\inventory\AnvilInventory;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\event\TranslationContainer;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -27,8 +29,8 @@ class Bedrock extends Solid{
|
||||
|
||||
protected $id = self::BEDROCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class BirchWoodStairs extends WoodStairs{
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* All Block classes are in here
|
||||
*/
|
||||
@ -54,6 +56,8 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
public static $hardness = null;
|
||||
/** @var \SplFixedArray */
|
||||
public static $transparent = null;
|
||||
/** @var \SplFixedArray */
|
||||
public static $diffusesSkyLight = null;
|
||||
|
||||
protected $id;
|
||||
protected $meta = 0;
|
||||
@ -70,6 +74,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
self::$solid = new \SplFixedArray(256);
|
||||
self::$hardness = new \SplFixedArray(256);
|
||||
self::$transparent = new \SplFixedArray(256);
|
||||
self::$diffusesSkyLight = new \SplFixedArray(256);
|
||||
self::$list[self::AIR] = Air::class;
|
||||
self::$list[self::STONE] = Stone::class;
|
||||
self::$list[self::GRASS] = Grass::class;
|
||||
@ -254,31 +259,20 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
for($data = 0; $data < 16; ++$data){
|
||||
self::$fullList[($id << 4) | $data] = new $class($data);
|
||||
}
|
||||
|
||||
self::$solid[$id] = $block->isSolid();
|
||||
self::$transparent[$id] = $block->isTransparent();
|
||||
self::$hardness[$id] = $block->getHardness();
|
||||
self::$light[$id] = $block->getLightLevel();
|
||||
|
||||
if($block->isSolid()){
|
||||
if($block->isTransparent()){
|
||||
if($block instanceof Liquid or $block instanceof Ice){
|
||||
self::$lightFilter[$id] = 2;
|
||||
}else{
|
||||
self::$lightFilter[$id] = 1;
|
||||
}
|
||||
}else{
|
||||
self::$lightFilter[$id] = 15;
|
||||
}
|
||||
}else{
|
||||
self::$lightFilter[$id] = 1;
|
||||
}
|
||||
}else{
|
||||
self::$lightFilter[$id] = 1;
|
||||
$block = new UnknownBlock($id);
|
||||
|
||||
for($data = 0; $data < 16; ++$data){
|
||||
self::$fullList[($id << 4) | $data] = new UnknownBlock($id, $data);
|
||||
}
|
||||
}
|
||||
|
||||
self::$solid[$id] = $block->isSolid();
|
||||
self::$transparent[$id] = $block->isTransparent();
|
||||
self::$hardness[$id] = $block->getHardness();
|
||||
self::$light[$id] = $block->getLightLevel();
|
||||
self::$lightFilter[$id] = $block->getLightFilter() + 1;
|
||||
self::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -419,6 +413,29 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of light this block will filter out when light passes through this block.
|
||||
* This value is used in light spread calculation.
|
||||
*
|
||||
* @return int 0-15
|
||||
*/
|
||||
public function getLightFilter() : int{
|
||||
return 15;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this block will diffuse sky light passing through it vertically.
|
||||
* Diffusion means that full-strength sky light passing through this block will not be reduced, but will start being filtered below the block.
|
||||
* Examples of this behaviour include leaves and cobwebs.
|
||||
*
|
||||
* Light-diffusing blocks are included by the heightmap.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function diffusesSkyLight() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* AKA: Block->isPlaceable
|
||||
*
|
||||
@ -472,6 +489,14 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether entities can climb up this block.
|
||||
* @return bool
|
||||
*/
|
||||
public function canClimb() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
interface BlockIds{
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
@ -27,8 +29,8 @@ class Bookshelf extends Solid{
|
||||
|
||||
protected $id = self::BOOKSHELF;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
@ -27,8 +29,8 @@ class BrewingStand extends Transparent{
|
||||
|
||||
protected $id = self::BREWING_STAND_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class Bricks extends Solid{
|
||||
|
||||
protected $id = self::BRICKS_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
@ -84,7 +86,7 @@ class Cactus extends Transparent{
|
||||
}
|
||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
if($this->getSide(0)->getId() !== self::CACTUS){
|
||||
if($this->meta == 0x0F){
|
||||
if($this->meta === 0x0f){
|
||||
for($y = 1; $y < 3; ++$y){
|
||||
$b = $this->getLevel()->getBlock(new Vector3($this->x, $this->y + $y, $this->z));
|
||||
if($b->getId() === self::AIR){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Effect;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class Clay extends Solid{
|
||||
|
||||
protected $id = self::CLAY_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class Coal extends Solid{
|
||||
|
||||
protected $id = self::COAL_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class CoalOre extends Solid{
|
||||
|
||||
protected $id = self::COAL_ORE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class Cobblestone extends Solid{
|
||||
|
||||
protected $id = self::COBBLESTONE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
@ -29,8 +31,8 @@ class Cobweb extends Flowable{
|
||||
|
||||
protected $id = self::COBWEB;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function hasEntityCollision(){
|
||||
@ -57,4 +59,8 @@ class Cobweb extends Flowable{
|
||||
//TODO: correct drops
|
||||
return [];
|
||||
}
|
||||
|
||||
public function diffusesSkyLight() : bool{
|
||||
return true;
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class CocoaBlock extends Solid{
|
||||
|
@ -19,11 +19,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
|
||||
@ -34,8 +37,7 @@ abstract class Crops 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){
|
||||
if($block->getSide(Vector3::SIDE_DOWN)->getId() === Block::FARMLAND){
|
||||
$this->getLevel()->setBlock($block, $this, true, true);
|
||||
|
||||
return true;
|
||||
@ -69,12 +71,12 @@ abstract class Crops extends Flowable{
|
||||
|
||||
public function onUpdate($type){
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
if($this->getSide(0)->isTransparent() === true){
|
||||
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
return Level::BLOCK_UPDATE_NORMAL;
|
||||
}
|
||||
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
|
||||
if(mt_rand(0, 2) == 1){
|
||||
if(mt_rand(0, 2) === 1){
|
||||
if($this->meta < 0x07){
|
||||
$block = clone $this;
|
||||
++$block->meta;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -29,8 +31,8 @@ class Dandelion extends Flowable{
|
||||
|
||||
protected $id = self::DANDELION;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class DarkOakWoodStairs extends WoodStairs{
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class DaylightSensor extends Transparent{
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\level\Level;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class DetectorRail extends Rail{
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class Diamond extends Solid{
|
||||
|
||||
protected $id = self::DIAMOND_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class DiamondOre extends Solid{
|
||||
|
||||
protected $id = self::DIAMOND_ORE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -29,8 +31,8 @@ class Dirt extends Solid{
|
||||
|
||||
protected $id = self::DIRT;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function canBeActivated(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class Emerald extends Solid{
|
||||
|
||||
protected $id = self::EMERALD_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class EmeraldOre extends Solid{
|
||||
|
||||
protected $id = self::EMERALD_ORE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\inventory\EnchantInventory;
|
||||
@ -34,8 +36,8 @@ class EnchantingTable extends Transparent{
|
||||
|
||||
protected $id = self::ENCHANTING_TABLE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
@ -27,8 +29,8 @@ class EndStone extends Solid{
|
||||
|
||||
protected $id = self::END_STONE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
@ -37,23 +39,24 @@ abstract class Fallable extends Solid{
|
||||
if($type === Level::BLOCK_UPDATE_NORMAL){
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === self::AIR or ($down instanceof Liquid)){
|
||||
$this->level->setBlock($this, Block::get(Block::AIR), true, true);
|
||||
$fall = Entity::createEntity("FallingSand", $this->getLevel(), new CompoundTag("", [
|
||||
"Pos" => new ListTag("Pos", [
|
||||
new ListTag("Pos", [
|
||||
new DoubleTag("", $this->x + 0.5),
|
||||
new DoubleTag("", $this->y),
|
||||
new DoubleTag("", $this->z + 0.5)
|
||||
]),
|
||||
"Motion" => new ListTag("Motion", [
|
||||
new ListTag("Motion", [
|
||||
new DoubleTag("", 0),
|
||||
new DoubleTag("", 0),
|
||||
new DoubleTag("", 0)
|
||||
]),
|
||||
"Rotation" => new ListTag("Rotation", [
|
||||
new ListTag("Rotation", [
|
||||
new FloatTag("", 0),
|
||||
new FloatTag("", 0)
|
||||
]),
|
||||
"TileID" => new IntTag("TileID", $this->getId()),
|
||||
"Data" => new ByteTag("Data", $this->getDamage()),
|
||||
new IntTag("TileID", $this->getId()),
|
||||
new ByteTag("Data", $this->getDamage()),
|
||||
]));
|
||||
|
||||
$fall->spawnToAll();
|
||||
|
@ -19,13 +19,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\Tool;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
|
||||
class Farmland extends Solid{
|
||||
class Farmland extends Transparent{
|
||||
|
||||
protected $id = self::FARMLAND;
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Arrow;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
abstract class Flowable extends Transparent{
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -27,8 +29,8 @@ class Glass extends Transparent{
|
||||
|
||||
protected $id = self::GLASS;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -27,8 +29,8 @@ class GlassPane extends Thin{
|
||||
|
||||
protected $id = self::GLASS_PANE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class Glowstone extends Transparent{
|
||||
|
||||
protected $id = self::GLOWSTONE_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class Gold extends Solid{
|
||||
|
||||
protected $id = self::GOLD_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class GoldOre extends Solid{
|
||||
|
||||
protected $id = self::GOLD_ORE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\event\block\BlockSpreadEvent;
|
||||
@ -35,8 +37,8 @@ class Grass extends Solid{
|
||||
|
||||
protected $id = self::GRASS;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function canBeActivated(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -29,8 +31,8 @@ class GrassPath extends Transparent{
|
||||
|
||||
protected $id = self::GRASS_PATH;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class Gravel extends Fallable{
|
||||
|
||||
protected $id = self::GRAVEL;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
@ -27,8 +29,8 @@ class HardenedClay extends Solid{
|
||||
|
||||
protected $id = self::HARDENED_CLAY;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class Ice extends Transparent{
|
||||
|
||||
protected $id = self::ICE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
@ -40,6 +42,10 @@ class Ice extends Transparent{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
public function getLightFilter() : int{
|
||||
return 2;
|
||||
}
|
||||
|
||||
public function getToolType(){
|
||||
return Tool::TYPE_PICKAXE;
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class Iron extends Solid{
|
||||
|
||||
protected $id = self::IRON_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class IronBars extends Thin{
|
||||
|
||||
protected $id = self::IRON_BARS;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class IronOre extends Solid{
|
||||
|
||||
protected $id = self::IRON_ORE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Tool;
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class JungleWoodStairs extends WoodStairs{
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
@ -52,6 +54,10 @@ class Ladder extends Transparent{
|
||||
return 0.4;
|
||||
}
|
||||
|
||||
public function canClimb() : bool{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function onEntityCollide(Entity $entity){
|
||||
$entity->resetFallDistance();
|
||||
$entity->onGround = true;
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class Lapis extends Solid{
|
||||
|
||||
protected $id = self::LAPIS_BLOCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getName(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
@ -28,8 +30,8 @@ class LapisOre extends Solid{
|
||||
|
||||
protected $id = self::LAPIS_ORE;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct($meta = 0){
|
||||
$this->meta = $meta;
|
||||
}
|
||||
|
||||
public function getHardness(){
|
||||
|
@ -19,6 +19,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Effect;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user