mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 03:06:55 +00:00
Compare commits
221 Commits
Author | SHA1 | Date | |
---|---|---|---|
2f43b054de | |||
23b5d64535 | |||
9afa0e5483 | |||
4eaea54b0e | |||
6b51bf4a80 | |||
cba8d86c4f | |||
2e834c8f5c | |||
f9873e9108 | |||
074baf7e1c | |||
2e0dd574e0 | |||
e16d8e31af | |||
3c93a57397 | |||
e2e927b328 | |||
a8dab25201 | |||
3de2b7969e | |||
8f486ea65d | |||
6b971b1761 | |||
6f36fa504b | |||
8e73842a93 | |||
e71e18fc88 | |||
e1bacb5c6d | |||
44697e784a | |||
65529ff2ce | |||
c346c45d42 | |||
c433fad0a7 | |||
8fad5a6e30 | |||
7a6f279825 | |||
10b72c895d | |||
d520928888 | |||
27767e7ddb | |||
243c12de7c | |||
372545e47e | |||
8913b48700 | |||
6ee4a0e090 | |||
8bd8da4bc6 | |||
9ba4144a71 | |||
9da7c6af27 | |||
109312284c | |||
51934614bc | |||
9e89f65094 | |||
9562711b84 | |||
30b49e0d22 | |||
a975868fc3 | |||
b38b932845 | |||
43cb19ebca | |||
769cc91543 | |||
278f37d3e0 | |||
02a6ca84a9 | |||
b8703d5dff | |||
37c2d78731 | |||
b7663e5815 | |||
1d0ffa06f8 | |||
768cfe3953 | |||
2822465f33 | |||
5da48f429f | |||
dbd0d04549 | |||
0f92ec6d2a | |||
791b4d8ef3 | |||
0b7ff6f2e7 | |||
af092b01e1 | |||
d811217755 | |||
d7f86f0240 | |||
5fe1d2e396 | |||
ddbb5363ef | |||
d3704bfae4 | |||
07f034d2da | |||
331ae5498f | |||
eebd90ec42 | |||
8e47a40b4c | |||
0f9fdf6442 | |||
5364e4de68 | |||
1099e2044b | |||
80d48161d3 | |||
fbe8485696 | |||
a150f39b02 | |||
71d17c50d6 | |||
3a18bdd6a0 | |||
96857c65b6 | |||
9826abd83e | |||
48c8c2a8c3 | |||
c83b7d9b69 | |||
c66dc7b273 | |||
5bf7350ee5 | |||
636cc1c199 | |||
62b6405371 | |||
9ecf23d3ee | |||
187f36fe38 | |||
dc89b48354 | |||
e6d1c1dfbc | |||
5a8812b1dc | |||
4b8e4123af | |||
45a4252c26 | |||
feaaa925a7 | |||
5221db1178 | |||
47321114eb | |||
a27c9409f1 | |||
854f851525 | |||
9003b38be3 | |||
a6a93f822f | |||
d4851a8f1f | |||
480a513f30 | |||
4fd3bee360 | |||
41fd7545e3 | |||
82dddde159 | |||
bc709efb77 | |||
cd98e6a23e | |||
cb591a98f4 | |||
e9d1af0aee | |||
0f545c410a | |||
1c2ed0836f | |||
6cf30dc813 | |||
f7d9247d39 | |||
3380aa3ac2 | |||
6a9cad8fb7 | |||
c9e598cdb9 | |||
a6e5b6e158 | |||
22a6b817d7 | |||
2cdf97b7b5 | |||
836cb67850 | |||
ab37df4484 | |||
93969197f7 | |||
946a1036f1 | |||
43410cdafb | |||
a99e15012c | |||
b22a2ef914 | |||
f7f7be896e | |||
254281cd5e | |||
5dfceeea98 | |||
4b9a142a5d | |||
0bacf51729 | |||
33f6b441d8 | |||
11b59498d9 | |||
d71a543d10 | |||
5e0c3333cf | |||
0f941410f6 | |||
504cc3bf8b | |||
6bd1491b8b | |||
658786f2f6 | |||
d34f3f1af3 | |||
8650c187f9 | |||
4b4820cf53 | |||
d33acc4fd0 | |||
f7de6eb59f | |||
75a0627bf2 | |||
8752e363c9 | |||
9ed1b5ca7f | |||
1cbb31f1db | |||
1393b4c4e2 | |||
2921c86b3c | |||
9c3a929b65 | |||
9abaa42cd7 | |||
77b9feb3c0 | |||
e0e2e1775f | |||
d2d65ce6cc | |||
ff2e982f22 | |||
daf56e990b | |||
3f5e83a322 | |||
5ecc5ed7e0 | |||
cd80ae00d4 | |||
beb5d72299 | |||
0eef634aab | |||
0ea166a551 | |||
6417cff618 | |||
a71af952ba | |||
93dd05a03e | |||
98f903783c | |||
5d47ea4337 | |||
c242d6213a | |||
4ad1093fd7 | |||
fc0782df02 | |||
bfaa224f6b | |||
de88f0fce1 | |||
9b078854c4 | |||
42f8e061a5 | |||
1455c38dbe | |||
75df6973df | |||
4763360e9e | |||
0299191e64 | |||
2664a1b4d8 | |||
4249c00c3e | |||
517c4e5143 | |||
69c343bb9b | |||
70df1579a8 | |||
ea9f9aa250 | |||
34a899e28b | |||
b80868040e | |||
a7f1181335 | |||
bf8a8b386e | |||
4b518f2a58 | |||
60b1f0a6e9 | |||
5934399a0d | |||
b42132a7c3 | |||
c05697f506 | |||
d4fe1b8ece | |||
9b2653fb6f | |||
ed88684e71 | |||
cbb9c4f298 | |||
660d42e8d1 | |||
dbeceb02f9 | |||
fd77dd0066 | |||
87ce87112b | |||
1d71f5edb3 | |||
0f620157e8 | |||
2323601f98 | |||
d34b94302f | |||
ec4c61e113 | |||
231e491bb9 | |||
69cdc6f13a | |||
dfeb62491a | |||
178eedb536 | |||
4975da2aae | |||
5946ec8819 | |||
abf0dee426 | |||
30f5a8fac6 | |||
f704061618 | |||
23dc6e09d8 | |||
15b7fc978e | |||
bb396174ba | |||
dcef3cba21 | |||
5f8a9f8747 | |||
84e41e6967 |
@ -4,3 +4,7 @@ root = yes
|
||||
[*]
|
||||
indent_size = 4
|
||||
indent_style = tab
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
|
@ -2,13 +2,14 @@ language: php
|
||||
|
||||
php:
|
||||
- 7.2
|
||||
- 7.3
|
||||
|
||||
before_script:
|
||||
# - pecl install channel://pecl.php.net/pthreads-3.1.6
|
||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.2
|
||||
- echo | pecl install channel://pecl.php.net/yaml-2.0.4
|
||||
- git clone https://github.com/pmmp/pthreads.git
|
||||
- cd pthreads
|
||||
- git checkout c8cfacda84f21032d6014b53e72bf345ac901dac
|
||||
- git checkout 6ca019c58b4fa09ee2ff490f2444e34bef0773d0
|
||||
- phpize
|
||||
- ./configure
|
||||
- make
|
||||
|
@ -27,10 +27,11 @@
|
||||
"pocketmine/raklib": "^0.12.0",
|
||||
"pocketmine/spl": "^0.3.0",
|
||||
"pocketmine/binaryutils": "^0.1.0",
|
||||
"pocketmine/nbt": "^0.2.1",
|
||||
"pocketmine/nbt": "^0.2.6",
|
||||
"pocketmine/math": "^0.2.0",
|
||||
"pocketmine/snooze": "^0.1.0",
|
||||
"daverandom/callback-validator": "dev-master"
|
||||
"daverandom/callback-validator": "dev-master",
|
||||
"adhocore/json-comment": "^0.0.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
108
composer.lock
generated
108
composer.lock
generated
@ -4,8 +4,52 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "2d120a3dd7d68958809c3662d1cb7c99",
|
||||
"content-hash": "2f5313e4ebd7b62c785cf683b27464b4",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/json-comment",
|
||||
"version": "v0.0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/adhocore/php-json-comment.git",
|
||||
"reference": "135356c7e7336ef59924f1d921c770045f937a76"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/adhocore/php-json-comment/zipball/135356c7e7336ef59924f1d921c770045f937a76",
|
||||
"reference": "135356c7e7336ef59924f1d921c770045f937a76",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8 || ^5.7 || ^6.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Ahc\\Json\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jitendra Adhikari",
|
||||
"email": "jiten.adhikary@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Lightweight JSON comment stripper library for PHP",
|
||||
"keywords": [
|
||||
"comment",
|
||||
"json",
|
||||
"strip-comment"
|
||||
],
|
||||
"time": "2018-08-01T12:27:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "daverandom/callback-validator",
|
||||
"version": "dev-master",
|
||||
@ -48,16 +92,16 @@
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/binaryutils",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/BinaryUtils.git",
|
||||
"reference": "54efeb978be0ff9335022729fe63c1e2077bf1be"
|
||||
"reference": "33f511715d22418c03368b49b45a6c25d6b33806"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/54efeb978be0ff9335022729fe63c1e2077bf1be",
|
||||
"reference": "54efeb978be0ff9335022729fe63c1e2077bf1be",
|
||||
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/33f511715d22418c03368b49b45a6c25d6b33806",
|
||||
"reference": "33f511715d22418c03368b49b45a6c25d6b33806",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -75,23 +119,23 @@
|
||||
],
|
||||
"description": "Classes and methods for conveniently handling binary data",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/BinaryUtils/tree/master",
|
||||
"source": "https://github.com/pmmp/BinaryUtils/tree/0.1.8",
|
||||
"issues": "https://github.com/pmmp/BinaryUtils/issues"
|
||||
},
|
||||
"time": "2018-08-26T18:11:05+00:00"
|
||||
"time": "2019-01-16T17:31:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/math",
|
||||
"version": "0.2.1",
|
||||
"version": "0.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Math.git",
|
||||
"reference": "ee299f5c9c444ca526c9c691b920f321458cf0b6"
|
||||
"reference": "b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Math/zipball/ee299f5c9c444ca526c9c691b920f321458cf0b6",
|
||||
"reference": "ee299f5c9c444ca526c9c691b920f321458cf0b6",
|
||||
"url": "https://api.github.com/repos/pmmp/Math/zipball/b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c",
|
||||
"reference": "b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -109,23 +153,23 @@
|
||||
],
|
||||
"description": "PHP library containing math related code used in PocketMine-MP",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/Math/tree/0.2.1",
|
||||
"source": "https://github.com/pmmp/Math/tree/0.2.2",
|
||||
"issues": "https://github.com/pmmp/Math/issues"
|
||||
},
|
||||
"time": "2018-08-15T15:43:27+00:00"
|
||||
"time": "2019-01-04T15:42:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/nbt",
|
||||
"version": "0.2.3",
|
||||
"version": "0.2.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/NBT.git",
|
||||
"reference": "291bf5cc2a94500eada1edbda51d15bed25a1e1c"
|
||||
"reference": "92eaf84dd61f700d3ec02ebd01b606cb5b1590d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/NBT/zipball/291bf5cc2a94500eada1edbda51d15bed25a1e1c",
|
||||
"reference": "291bf5cc2a94500eada1edbda51d15bed25a1e1c",
|
||||
"url": "https://api.github.com/repos/pmmp/NBT/zipball/92eaf84dd61f700d3ec02ebd01b606cb5b1590d4",
|
||||
"reference": "92eaf84dd61f700d3ec02ebd01b606cb5b1590d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -150,23 +194,23 @@
|
||||
],
|
||||
"description": "PHP library for working with Named Binary Tags",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/NBT/tree/0.2.3",
|
||||
"source": "https://github.com/pmmp/NBT/tree/0.2.6",
|
||||
"issues": "https://github.com/pmmp/NBT/issues"
|
||||
},
|
||||
"time": "2018-12-03T16:08:28+00:00"
|
||||
"time": "2019-02-07T16:28:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/raklib",
|
||||
"version": "0.12.0",
|
||||
"version": "0.12.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/RakLib.git",
|
||||
"reference": "922da28efd828e2af6c19db1676ea9b6a267071c"
|
||||
"reference": "54a36d55eeba0a182e00439920ee2fcfa8c72bf3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/922da28efd828e2af6c19db1676ea9b6a267071c",
|
||||
"reference": "922da28efd828e2af6c19db1676ea9b6a267071c",
|
||||
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/54a36d55eeba0a182e00439920ee2fcfa8c72bf3",
|
||||
"reference": "54a36d55eeba0a182e00439920ee2fcfa8c72bf3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -191,23 +235,23 @@
|
||||
],
|
||||
"description": "A RakNet server implementation written in PHP",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/RakLib/tree/0.12.0",
|
||||
"source": "https://github.com/pmmp/RakLib/tree/0.12",
|
||||
"issues": "https://github.com/pmmp/RakLib/issues"
|
||||
},
|
||||
"time": "2018-06-13T10:06:14+00:00"
|
||||
"time": "2019-01-21T14:17:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/snooze",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pmmp/Snooze.git",
|
||||
"reference": "3cc9d0164230889acb08e22cc126133809e9d346"
|
||||
"reference": "b7bd231bdb75e69300cac89ccd515fc731c38c40"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/3cc9d0164230889acb08e22cc126133809e9d346",
|
||||
"reference": "3cc9d0164230889acb08e22cc126133809e9d346",
|
||||
"url": "https://api.github.com/repos/pmmp/Snooze/zipball/b7bd231bdb75e69300cac89ccd515fc731c38c40",
|
||||
"reference": "b7bd231bdb75e69300cac89ccd515fc731c38c40",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -225,10 +269,10 @@
|
||||
],
|
||||
"description": "Thread notification management library for code using the pthreads extension",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/Snooze/tree/0.1.0",
|
||||
"source": "https://github.com/pmmp/Snooze/tree/0.1.1",
|
||||
"issues": "https://github.com/pmmp/Snooze/issues"
|
||||
},
|
||||
"time": "2018-06-13T09:36:11+00:00"
|
||||
"time": "2019-01-04T15:54:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pocketmine/spl",
|
||||
@ -258,7 +302,7 @@
|
||||
],
|
||||
"description": "Standard library files required by PocketMine-MP and related projects",
|
||||
"support": {
|
||||
"source": "https://github.com/pmmp/SPL/tree/master"
|
||||
"source": "https://github.com/pmmp/SPL/tree/0.3.2"
|
||||
},
|
||||
"time": "2018-08-12T15:17:39+00:00"
|
||||
}
|
||||
|
19
doxygen.conf
19
doxygen.conf
@ -51,7 +51,7 @@ PROJECT_BRIEF =
|
||||
# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
|
||||
# to the output directory.
|
||||
|
||||
PROJECT_LOGO = "/home/jenkins/PocketMine-h-64.png"
|
||||
PROJECT_LOGO =
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
|
||||
# into which the generated documentation will be written. If a relative path is
|
||||
@ -240,7 +240,7 @@ OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
# qualified scopes will look different, etc.
|
||||
# The default value is: NO.
|
||||
|
||||
OPTIMIZE_OUTPUT_JAVA = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
|
||||
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
|
||||
# sources. Doxygen will then generate output that is tailored for Fortran.
|
||||
@ -737,7 +737,9 @@ WARN_LOGFILE =
|
||||
# spaces.
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = ./
|
||||
INPUT = ./src \
|
||||
./vendor/pocketmine \
|
||||
./README.md
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
@ -757,9 +759,7 @@ INPUT_ENCODING = UTF-8
|
||||
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
|
||||
# *.qsf, *.as and *.js.
|
||||
|
||||
FILE_PATTERNS = *.php \
|
||||
*.sh \
|
||||
*.md
|
||||
FILE_PATTERNS = *.php
|
||||
|
||||
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
||||
# be searched for input files as well.
|
||||
@ -793,7 +793,10 @@ EXCLUDE_SYMLINKS = YES
|
||||
EXCLUDE_PATTERNS = */bin/* \
|
||||
*/players/* \
|
||||
*/worlds/* \
|
||||
*/plugins/*
|
||||
*/plugins/* \
|
||||
*/plugin_data/* \
|
||||
*/tests/* \
|
||||
*/stubs/*
|
||||
|
||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
@ -878,7 +881,7 @@ FILTER_SOURCE_PATTERNS =
|
||||
# (index.html). This can be useful if you have a project on for instance GitHub
|
||||
# and want to reuse the introduction page also for the doxygen output.
|
||||
|
||||
USE_MDFILE_AS_MAINPAGE = README.md
|
||||
USE_MDFILE_AS_MAINPAGE = ./README.md
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
|
@ -30,9 +30,70 @@ use pocketmine\plugin\PluginManager;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\VersionString;
|
||||
use raklib\RakLib;
|
||||
use function base64_encode;
|
||||
use function date;
|
||||
use function error_get_last;
|
||||
use function fclose;
|
||||
use function file;
|
||||
use function file_exists;
|
||||
use function file_get_contents;
|
||||
use function fopen;
|
||||
use function fwrite;
|
||||
use function get_loaded_extensions;
|
||||
use function implode;
|
||||
use function is_dir;
|
||||
use function is_resource;
|
||||
use function json_encode;
|
||||
use function json_last_error_msg;
|
||||
use function max;
|
||||
use function mkdir;
|
||||
use function ob_end_clean;
|
||||
use function ob_get_contents;
|
||||
use function ob_start;
|
||||
use function php_uname;
|
||||
use function phpinfo;
|
||||
use function phpversion;
|
||||
use function preg_replace;
|
||||
use function str_split;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
use function time;
|
||||
use function zend_version;
|
||||
use function zlib_encode;
|
||||
use const E_COMPILE_ERROR;
|
||||
use const E_COMPILE_WARNING;
|
||||
use const E_CORE_ERROR;
|
||||
use const E_CORE_WARNING;
|
||||
use const E_DEPRECATED;
|
||||
use const E_ERROR;
|
||||
use const E_NOTICE;
|
||||
use const E_PARSE;
|
||||
use const E_RECOVERABLE_ERROR;
|
||||
use const E_STRICT;
|
||||
use const E_USER_DEPRECATED;
|
||||
use const E_USER_ERROR;
|
||||
use const E_USER_NOTICE;
|
||||
use const E_USER_WARNING;
|
||||
use const E_WARNING;
|
||||
use const FILE_IGNORE_NEW_LINES;
|
||||
use const JSON_UNESCAPED_SLASHES;
|
||||
use const PHP_EOL;
|
||||
use const PHP_OS;
|
||||
|
||||
class CrashDump{
|
||||
|
||||
/**
|
||||
* Crashdump data format version, used by the crash archive to decide how to decode the crashdump
|
||||
* This should be incremented when backwards incompatible changes are introduced, such as fields being removed or
|
||||
* having their content changed, version format changing, etc.
|
||||
* It is not necessary to increase this when adding new fields.
|
||||
*/
|
||||
private const FORMAT_VERSION = 2;
|
||||
|
||||
private const PLUGIN_INVOLVEMENT_NONE = "none";
|
||||
private const PLUGIN_INVOLVEMENT_DIRECT = "direct";
|
||||
private const PLUGIN_INVOLVEMENT_INDIRECT = "indirect";
|
||||
|
||||
/** @var Server */
|
||||
private $server;
|
||||
private $fp;
|
||||
@ -54,6 +115,7 @@ class CrashDump{
|
||||
if(!is_resource($this->fp)){
|
||||
throw new \RuntimeException("Could not create Crash Dump");
|
||||
}
|
||||
$this->data["format_version"] = self::FORMAT_VERSION;
|
||||
$this->data["time"] = $this->time;
|
||||
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", $this->time));
|
||||
$this->addLine();
|
||||
@ -85,7 +147,11 @@ class CrashDump{
|
||||
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
|
||||
$this->addLine();
|
||||
$this->addLine("===BEGIN CRASH DUMP===");
|
||||
$this->encodedData = zlib_encode(json_encode($this->data, JSON_UNESCAPED_SLASHES), ZLIB_ENCODING_DEFLATE, 9);
|
||||
$json = json_encode($this->data, JSON_UNESCAPED_SLASHES);
|
||||
if($json === false){
|
||||
throw new \RuntimeException("Failed to encode crashdump JSON: " . json_last_error_msg());
|
||||
}
|
||||
$this->encodedData = zlib_encode($json, ZLIB_ENCODING_DEFLATE, 9);
|
||||
foreach(str_split(base64_encode($this->encodedData), 76) as $line){
|
||||
$this->addLine($line);
|
||||
}
|
||||
@ -150,7 +216,7 @@ class CrashDump{
|
||||
$error = $lastExceptionError;
|
||||
}else{
|
||||
$error = (array) error_get_last();
|
||||
$error["trace"] = Utils::getTrace(4); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
|
||||
$error["trace"] = Utils::currentTrace(3); //Skipping CrashDump->baseCrash, CrashDump->construct, Server->crashDump
|
||||
$errorConversion = [
|
||||
E_ERROR => "E_ERROR",
|
||||
E_WARNING => "E_WARNING",
|
||||
@ -177,6 +243,9 @@ class CrashDump{
|
||||
}
|
||||
|
||||
if(isset($lastError)){
|
||||
if(isset($lastError["trace"])){
|
||||
$lastError["trace"] = Utils::printableTrace($lastError["trace"]);
|
||||
}
|
||||
$this->data["lastError"] = $lastError;
|
||||
}
|
||||
|
||||
@ -188,24 +257,16 @@ class CrashDump{
|
||||
$this->addLine("Line: " . $error["line"]);
|
||||
$this->addLine("Type: " . $error["type"]);
|
||||
|
||||
if(strpos($error["file"], "src/pocketmine/") === false and strpos($error["file"], "vendor/pocketmine/") === false and file_exists($error["fullFile"])){
|
||||
$this->addLine();
|
||||
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
|
||||
$this->data["plugin"] = true;
|
||||
|
||||
$reflection = new \ReflectionClass(PluginBase::class);
|
||||
$file = $reflection->getProperty("file");
|
||||
$file->setAccessible(true);
|
||||
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
|
||||
$filePath = Utils::cleanPath($file->getValue($plugin));
|
||||
if(strpos($error["file"], $filePath) === 0){
|
||||
$this->data["plugin"] = $plugin->getName();
|
||||
$this->addLine("BAD PLUGIN: " . $plugin->getDescription()->getFullName());
|
||||
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_NONE;
|
||||
if(!$this->determinePluginFromFile($error["fullFile"], true)){ //fatal errors won't leave any stack trace
|
||||
foreach($error["trace"] as $frame){
|
||||
if(!isset($frame["file"])){
|
||||
continue; //PHP core
|
||||
}
|
||||
if($this->determinePluginFromFile($frame["file"], false)){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$this->data["plugin"] = false;
|
||||
}
|
||||
|
||||
$this->addLine();
|
||||
@ -222,20 +283,48 @@ class CrashDump{
|
||||
|
||||
$this->addLine();
|
||||
$this->addLine("Backtrace:");
|
||||
foreach(($this->data["trace"] = $error["trace"]) as $line){
|
||||
foreach(($this->data["trace"] = Utils::printableTrace($error["trace"])) as $line){
|
||||
$this->addLine($line);
|
||||
}
|
||||
$this->addLine();
|
||||
}
|
||||
|
||||
private function determinePluginFromFile(string $filePath, bool $crashFrame) : bool{
|
||||
$frameCleanPath = Utils::cleanPath($filePath); //this will be empty in phar stub
|
||||
if($frameCleanPath !== "" and strpos($frameCleanPath, "src/pocketmine/") === false and strpos($frameCleanPath, "vendor/pocketmine/") === false and file_exists($filePath)){
|
||||
$this->addLine();
|
||||
if($crashFrame){
|
||||
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
|
||||
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_DIRECT;
|
||||
}else{
|
||||
$this->addLine("A PLUGIN WAS INVOLVED IN THIS CRASH");
|
||||
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_INDIRECT;
|
||||
}
|
||||
|
||||
$reflection = new \ReflectionClass(PluginBase::class);
|
||||
$file = $reflection->getProperty("file");
|
||||
$file->setAccessible(true);
|
||||
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
|
||||
$filePath = Utils::cleanPath($file->getValue($plugin));
|
||||
if(strpos($frameCleanPath, $filePath) === 0){
|
||||
$this->data["plugin"] = $plugin->getName();
|
||||
$this->addLine("BAD PLUGIN: " . $plugin->getDescription()->getFullName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function generalData(){
|
||||
$version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER);
|
||||
$this->data["general"] = [];
|
||||
$this->data["general"]["name"] = $this->server->getName();
|
||||
$this->data["general"]["version"] = $version->getFullVersion(false);
|
||||
$this->data["general"]["build"] = $version->getBuild();
|
||||
$this->data["general"]["base_version"] = \pocketmine\BASE_VERSION;
|
||||
$this->data["general"]["build"] = \pocketmine\BUILD_NUMBER;
|
||||
$this->data["general"]["is_dev"] = \pocketmine\IS_DEVELOPMENT_BUILD;
|
||||
$this->data["general"]["protocol"] = ProtocolInfo::CURRENT_PROTOCOL;
|
||||
$this->data["general"]["api"] = \pocketmine\BASE_VERSION;
|
||||
$this->data["general"]["git"] = \pocketmine\GIT_COMMIT;
|
||||
$this->data["general"]["raklib"] = RakLib::VERSION;
|
||||
$this->data["general"]["uname"] = php_uname("a");
|
||||
|
@ -28,6 +28,39 @@ use pocketmine\scheduler\DumpWorkerMemoryTask;
|
||||
use pocketmine\scheduler\GarbageCollectionTask;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\Utils;
|
||||
use function arsort;
|
||||
use function count;
|
||||
use function fclose;
|
||||
use function file_exists;
|
||||
use function file_put_contents;
|
||||
use function fopen;
|
||||
use function fwrite;
|
||||
use function gc_collect_cycles;
|
||||
use function gc_disable;
|
||||
use function gc_enable;
|
||||
use function get_class;
|
||||
use function get_declared_classes;
|
||||
use function implode;
|
||||
use function ini_get;
|
||||
use function ini_set;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function is_resource;
|
||||
use function is_string;
|
||||
use function json_encode;
|
||||
use function min;
|
||||
use function mkdir;
|
||||
use function preg_match;
|
||||
use function print_r;
|
||||
use function round;
|
||||
use function spl_object_hash;
|
||||
use function sprintf;
|
||||
use function strlen;
|
||||
use function strtoupper;
|
||||
use function substr;
|
||||
use const JSON_PRETTY_PRINT;
|
||||
use const JSON_UNESCAPED_SLASHES;
|
||||
use const SORT_NUMERIC;
|
||||
|
||||
class MemoryManager{
|
||||
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine;
|
||||
use pocketmine\block\Bed;
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\BlockFactory;
|
||||
use pocketmine\block\UnknownBlock;
|
||||
use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\entity\Effect;
|
||||
@ -101,6 +102,7 @@ use pocketmine\network\mcpe\PlayerNetworkSessionAdapter;
|
||||
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
|
||||
use pocketmine\network\mcpe\protocol\AnimatePacket;
|
||||
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
|
||||
use pocketmine\network\mcpe\protocol\AvailableEntityIdentifiersPacket;
|
||||
use pocketmine\network\mcpe\protocol\BatchPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
|
||||
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
|
||||
@ -120,6 +122,7 @@ use pocketmine\network\mcpe\protocol\MobEffectPacket;
|
||||
use pocketmine\network\mcpe\protocol\MobEquipmentPacket;
|
||||
use pocketmine\network\mcpe\protocol\ModalFormRequestPacket;
|
||||
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
|
||||
use pocketmine\network\mcpe\protocol\NetworkChunkPublisherUpdatePacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayerActionPacket;
|
||||
use pocketmine\network\mcpe\protocol\PlayStatusPacket;
|
||||
use pocketmine\network\mcpe\protocol\ProtocolInfo;
|
||||
@ -158,6 +161,41 @@ use pocketmine\tile\Tile;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\UUID;
|
||||
use function abs;
|
||||
use function array_merge;
|
||||
use function assert;
|
||||
use function base64_decode;
|
||||
use function ceil;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function floor;
|
||||
use function fmod;
|
||||
use function get_class;
|
||||
use function gettype;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function is_int;
|
||||
use function is_object;
|
||||
use function is_string;
|
||||
use function json_encode;
|
||||
use function json_last_error_msg;
|
||||
use function lcg_value;
|
||||
use function max;
|
||||
use function microtime;
|
||||
use function min;
|
||||
use function preg_match;
|
||||
use function round;
|
||||
use function spl_object_hash;
|
||||
use function sqrt;
|
||||
use function strlen;
|
||||
use function strpos;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
use function trim;
|
||||
use function ucfirst;
|
||||
use const M_PI;
|
||||
use const M_SQRT3;
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
|
||||
/**
|
||||
@ -276,7 +314,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
/** @var int */
|
||||
protected $spawnThreshold;
|
||||
/** @var int */
|
||||
protected $chunkLoadCount = 0;
|
||||
protected $spawnChunkLoadCount = 0;
|
||||
/** @var int */
|
||||
protected $chunksPerTick;
|
||||
|
||||
@ -325,6 +363,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
/** @var Form[] */
|
||||
protected $forms = [];
|
||||
|
||||
/** @var float */
|
||||
protected $lastRightClickTime = 0.0;
|
||||
/** @var Vector3|null */
|
||||
protected $lastRightClickPos = null;
|
||||
|
||||
/**
|
||||
* @return TranslationContainer|string
|
||||
*/
|
||||
@ -434,8 +477,11 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
|
||||
public function setFlying(bool $value){
|
||||
$this->flying = $value;
|
||||
$this->sendSettings();
|
||||
if($this->flying !== $value){
|
||||
$this->flying = $value;
|
||||
$this->resetFallDistance();
|
||||
$this->sendSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public function isFlying() : bool{
|
||||
@ -647,14 +693,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
$this->perm->recalculatePermissions();
|
||||
|
||||
if($this->hasPermission(Server::BROADCAST_CHANNEL_USERS)){
|
||||
$permManager->subscribeToPermission(Server::BROADCAST_CHANNEL_USERS, $this);
|
||||
}
|
||||
if($this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE)){
|
||||
$permManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this);
|
||||
}
|
||||
|
||||
if($this->spawned){
|
||||
if($this->hasPermission(Server::BROADCAST_CHANNEL_USERS)){
|
||||
$permManager->subscribeToPermission(Server::BROADCAST_CHANNEL_USERS, $this);
|
||||
}
|
||||
if($this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE)){
|
||||
$permManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this);
|
||||
}
|
||||
|
||||
$this->sendCommandData();
|
||||
}
|
||||
}
|
||||
@ -669,12 +715,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
public function sendCommandData(){
|
||||
$pk = new AvailableCommandsPacket();
|
||||
foreach($this->server->getCommandMap()->getCommands() as $name => $command){
|
||||
if(isset($pk->commandData[$command->getName()]) or $command->getName() === "help"){
|
||||
if(isset($pk->commandData[$command->getName()]) or $command->getName() === "help" or !$command->testPermissionSilent($this)){
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = new CommandData();
|
||||
$data->commandName = $command->getName();
|
||||
//TODO: commands containing uppercase letters in the name crash 1.9.0 client
|
||||
$data->commandName = strtolower($command->getName());
|
||||
$data->commandDescription = $this->server->getLanguage()->translateString($command->getDescription());
|
||||
$data->flags = 0;
|
||||
$data->permission = 0;
|
||||
@ -962,8 +1009,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
|
||||
$this->usedChunks[Level::chunkHash($x, $z)] = true;
|
||||
$this->chunkLoadCount++;
|
||||
|
||||
$this->dataPacket($payload);
|
||||
|
||||
if($this->spawned){
|
||||
@ -974,8 +1019,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
if($this->chunkLoadCount >= $this->spawnThreshold and !$this->spawned){
|
||||
$this->doFirstSpawn();
|
||||
if($this->spawnChunkLoadCount !== -1 and ++$this->spawnChunkLoadCount >= $this->spawnThreshold){
|
||||
$this->sendPlayStatus(PlayStatusPacket::PLAYER_SPAWN);
|
||||
$this->spawnChunkLoadCount = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1013,11 +1059,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
Timings::$playerChunkSendTimer->stopTiming();
|
||||
}
|
||||
|
||||
protected function doFirstSpawn(){
|
||||
public function doFirstSpawn(){
|
||||
if($this->spawned){
|
||||
return; //avoid player spawning twice (this can only happen on 3.x with a custom malicious client)
|
||||
}
|
||||
$this->spawned = true;
|
||||
|
||||
$this->sendPlayStatus(PlayStatusPacket::PLAYER_SPAWN);
|
||||
|
||||
if($this->hasPermission(Server::BROADCAST_CHANNEL_USERS)){
|
||||
PermissionManager::getInstance()->subscribeToPermission(Server::BROADCAST_CHANNEL_USERS, $this);
|
||||
}
|
||||
@ -1035,6 +1082,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$this->server->broadcastMessage($ev->getJoinMessage());
|
||||
}
|
||||
|
||||
$this->setImmobile(false);
|
||||
$this->noDamageTicks = 60;
|
||||
|
||||
foreach($this->usedChunks as $index => $c){
|
||||
@ -1071,8 +1119,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
Timings::$playerChunkOrderTimer->startTiming();
|
||||
|
||||
$this->nextChunkOrderRun = 200;
|
||||
|
||||
$radius = $this->server->getAllowedViewDistance($this->viewDistance);
|
||||
$radiusSquared = $radius ** 2;
|
||||
|
||||
@ -1149,6 +1195,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
|
||||
$this->loadQueue = $newOrder;
|
||||
if(!empty($this->loadQueue) or !empty($unloadChunks)){
|
||||
$pk = new NetworkChunkPublisherUpdatePacket();
|
||||
$pk->x = $this->getFloorX();
|
||||
$pk->y = $this->getFloorY();
|
||||
$pk->z = $this->getFloorZ();
|
||||
$pk->radius = $this->viewDistance * 16; //blocks, not chunks >.>
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
|
||||
Timings::$playerChunkOrderTimer->stopTiming();
|
||||
}
|
||||
@ -1361,19 +1415,17 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
$this->allowFlight = $this->isCreative();
|
||||
if($this->isSpectator()){
|
||||
$this->flying = true;
|
||||
$this->setFlying(true);
|
||||
$this->keepMovement = true;
|
||||
$this->despawnFromAll();
|
||||
}else{
|
||||
$this->keepMovement = $this->allowMovementCheats;
|
||||
if($this->isSurvival()){
|
||||
$this->flying = false;
|
||||
$this->setFlying(false);
|
||||
}
|
||||
$this->spawnToAll();
|
||||
}
|
||||
|
||||
$this->resetFallDistance();
|
||||
|
||||
$this->namedtag->setInt("playerGameType", $this->gamemode);
|
||||
if(!$client){ //Gamemode changed by server, do not send for client changes
|
||||
$this->sendGamemode();
|
||||
@ -1599,7 +1651,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}else{
|
||||
$this->broadcastMovement();
|
||||
|
||||
$distance = $from->distance($to);
|
||||
$distance = sqrt((($from->x - $to->x) ** 2) + (($from->z - $to->z) ** 2));
|
||||
//TODO: check swimming (adds 0.015 exhaustion in MCPE)
|
||||
if($this->isSprinting()){
|
||||
$this->exhaust(0.1 * $distance, PlayerExhaustEvent::CAUSE_SPRINTING);
|
||||
@ -1630,6 +1682,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$this->newPosition = null;
|
||||
}
|
||||
|
||||
public function fall(float $fallDistance) : void{
|
||||
if(!$this->flying){
|
||||
parent::fall($fallDistance);
|
||||
}
|
||||
}
|
||||
|
||||
public function jump() : void{
|
||||
(new PlayerJumpEvent($this))->call();
|
||||
parent::jump();
|
||||
@ -1762,7 +1820,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->nextChunkOrderRun-- <= 0){
|
||||
if($this->nextChunkOrderRun !== PHP_INT_MAX and $this->nextChunkOrderRun-- <= 0){
|
||||
$this->nextChunkOrderRun = PHP_INT_MAX;
|
||||
$this->orderChunks();
|
||||
}
|
||||
|
||||
@ -2087,12 +2146,15 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$pk->worldName = $this->server->getMotd();
|
||||
$this->dataPacket($pk);
|
||||
|
||||
$this->sendDataPacket(new AvailableEntityIdentifiersPacket());
|
||||
|
||||
$this->level->sendTime($this);
|
||||
|
||||
$this->sendAttributes(true);
|
||||
$this->setNameTagVisible();
|
||||
$this->setNameTagAlwaysVisible();
|
||||
$this->setCanClimb();
|
||||
$this->setImmobile(); //disable pre-spawn movement
|
||||
|
||||
$this->server->getLogger()->info($this->getServer()->getLanguage()->translateString("pocketmine.player.logIn", [
|
||||
TextFormat::AQUA . $this->username . TextFormat::WHITE,
|
||||
@ -2252,7 +2314,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
if($action !== null){
|
||||
$actions[] = $action;
|
||||
}
|
||||
}catch(\Exception $e){
|
||||
}catch(\UnexpectedValueException $e){
|
||||
$this->server->getLogger()->debug("Unhandled inventory action from " . $this->getName() . ": " . $e->getMessage());
|
||||
$this->sendAllInventories();
|
||||
return false;
|
||||
@ -2322,6 +2384,19 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$type = $packet->trData->actionType;
|
||||
switch($type){
|
||||
case InventoryTransactionPacket::USE_ITEM_ACTION_CLICK_BLOCK:
|
||||
//TODO: start hack for client spam bug
|
||||
$spamBug = ($this->lastRightClickPos !== null and
|
||||
microtime(true) - $this->lastRightClickTime < 0.1 and //100ms
|
||||
$this->lastRightClickPos->distanceSquared($packet->trData->clickPos) < 0.00001 //signature spam bug has 0 distance, but allow some error
|
||||
);
|
||||
//get rid of continued spam if the player clicks and holds right-click
|
||||
$this->lastRightClickPos = clone $packet->trData->clickPos;
|
||||
$this->lastRightClickTime = microtime(true);
|
||||
if($spamBug){
|
||||
return true;
|
||||
}
|
||||
//TODO: end hack for client spam bug
|
||||
|
||||
$this->setUsingItem(false);
|
||||
|
||||
if(!$this->canInteract($blockVector->add(0.5, 0.5, 0.5), 13) or $this->isSpectator()){
|
||||
@ -2619,6 +2694,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
if(!$this->spawned or !$this->isAlive()){
|
||||
return true;
|
||||
}
|
||||
if($packet->action === InteractPacket::ACTION_MOUSEOVER and $packet->target === 0){
|
||||
//TODO HACK: silence useless spam (MCPE 1.8)
|
||||
//this packet is EXPECTED to only be sent when interacting with an entity, but due to some messy Mojang
|
||||
//hacks, it also sends it when changing the held item now, which causes us to think the inventory was closed
|
||||
//when it wasn't.
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->doCloseInventory();
|
||||
|
||||
@ -2642,6 +2724,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
|
||||
public function handleBlockPickRequest(BlockPickRequestPacket $packet) : bool{
|
||||
$block = $this->level->getBlockAt($packet->blockX, $packet->blockY, $packet->blockZ);
|
||||
if($block instanceof UnknownBlock){
|
||||
return true;
|
||||
}
|
||||
|
||||
$item = $block->getPickedItem();
|
||||
if($packet->addUserData){
|
||||
@ -2866,8 +2951,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
$ev->call();
|
||||
if($ev->isCancelled()){
|
||||
$this->sendSettings();
|
||||
}else{
|
||||
}else{ //don't use setFlying() here, to avoid feedback loops
|
||||
$this->flying = $ev->isFlying();
|
||||
$this->resetFallDistance();
|
||||
}
|
||||
|
||||
$handled = true;
|
||||
@ -3379,92 +3465,82 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
*/
|
||||
final public function close($message = "", string $reason = "generic reason", bool $notify = true) : void{
|
||||
if($this->isConnected() and !$this->closed){
|
||||
if($notify and strlen($reason) > 0){
|
||||
$pk = new DisconnectPacket();
|
||||
$pk->message = $reason;
|
||||
$this->directDataPacket($pk);
|
||||
}
|
||||
$this->interface->close($this, $notify ? $reason : "");
|
||||
$this->sessionAdapter = null;
|
||||
|
||||
try{
|
||||
if($notify and strlen($reason) > 0){
|
||||
$pk = new DisconnectPacket();
|
||||
$pk->message = $reason;
|
||||
$this->directDataPacket($pk);
|
||||
PermissionManager::getInstance()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this);
|
||||
PermissionManager::getInstance()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this);
|
||||
|
||||
$this->stopSleep();
|
||||
|
||||
if($this->spawned){
|
||||
$ev = new PlayerQuitEvent($this, $message, $reason);
|
||||
$ev->call();
|
||||
if($ev->getQuitMessage() != ""){
|
||||
$this->server->broadcastMessage($ev->getQuitMessage());
|
||||
}
|
||||
$this->interface->close($this, $notify ? $reason : "");
|
||||
$this->sessionAdapter = null;
|
||||
|
||||
PermissionManager::getInstance()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this);
|
||||
PermissionManager::getInstance()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this);
|
||||
$this->save();
|
||||
}
|
||||
|
||||
$this->stopSleep();
|
||||
|
||||
if($this->spawned){
|
||||
$ev = new PlayerQuitEvent($this, $message, $reason);
|
||||
$ev->call();
|
||||
if($ev->getQuitMessage() != ""){
|
||||
$this->server->broadcastMessage($ev->getQuitMessage());
|
||||
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->usedChunks = [];
|
||||
$this->loadQueue = [];
|
||||
|
||||
try{
|
||||
$this->save();
|
||||
}catch(\Throwable $e){
|
||||
$this->server->getLogger()->critical("Failed to save player data for " . $this->getName());
|
||||
$this->server->getLogger()->logException($e);
|
||||
if($this->loggedIn){
|
||||
$this->server->onPlayerLogout($this);
|
||||
foreach($this->server->getOnlinePlayers() as $player){
|
||||
if(!$player->canSee($this)){
|
||||
$player->showPlayer($this);
|
||||
}
|
||||
}
|
||||
$this->hiddenPlayers = [];
|
||||
}
|
||||
|
||||
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->usedChunks = [];
|
||||
$this->loadQueue = [];
|
||||
$this->removeAllWindows(true);
|
||||
$this->windows = [];
|
||||
$this->windowIndex = [];
|
||||
$this->cursorInventory = null;
|
||||
$this->craftingGrid = null;
|
||||
|
||||
if($this->loggedIn){
|
||||
$this->server->onPlayerLogout($this);
|
||||
foreach($this->server->getOnlinePlayers() as $player){
|
||||
if(!$player->canSee($this)){
|
||||
$player->showPlayer($this);
|
||||
}
|
||||
}
|
||||
$this->hiddenPlayers = [];
|
||||
}
|
||||
if($this->constructed){
|
||||
parent::close();
|
||||
}
|
||||
$this->spawned = false;
|
||||
|
||||
$this->removeAllWindows(true);
|
||||
$this->windows = [];
|
||||
$this->windowIndex = [];
|
||||
$this->cursorInventory = null;
|
||||
$this->craftingGrid = null;
|
||||
if($this->loggedIn){
|
||||
$this->loggedIn = false;
|
||||
$this->server->removeOnlinePlayer($this);
|
||||
}
|
||||
|
||||
if($this->constructed){
|
||||
parent::close();
|
||||
}
|
||||
$this->spawned = false;
|
||||
$this->server->removePlayer($this);
|
||||
|
||||
if($this->loggedIn){
|
||||
$this->loggedIn = false;
|
||||
$this->server->removeOnlinePlayer($this);
|
||||
}
|
||||
$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->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;
|
||||
|
||||
$this->spawnPosition = null;
|
||||
|
||||
if($this->perm !== null){
|
||||
$this->perm->clearPermissions();
|
||||
$this->perm = null;
|
||||
}
|
||||
}catch(\Throwable $e){
|
||||
$this->server->getLogger()->logException($e);
|
||||
}finally{
|
||||
$this->server->removePlayer($this);
|
||||
if($this->perm !== null){
|
||||
$this->perm->clearPermissions();
|
||||
$this->perm = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3565,10 +3641,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
}
|
||||
|
||||
protected function onDeathUpdate(int $tickDiff) : bool{
|
||||
if(parent::onDeathUpdate($tickDiff)){
|
||||
$this->despawnFromAll(); //non-player entities rely on close() to do this for them
|
||||
}
|
||||
|
||||
parent::onDeathUpdate($tickDiff);
|
||||
return false; //never flag players for despawn
|
||||
}
|
||||
|
||||
@ -3822,13 +3895,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
* @param Inventory $inventory
|
||||
* @param bool $force Forces removal of permanent windows such as normal inventory, cursor
|
||||
*
|
||||
* @throws \BadMethodCallException if trying to remove a fixed inventory window without the `force` parameter as true
|
||||
* @throws \InvalidArgumentException if trying to remove a fixed inventory window without the `force` parameter as true
|
||||
*/
|
||||
public function removeWindow(Inventory $inventory, bool $force = false){
|
||||
$id = $this->windows[$hash = spl_object_hash($inventory)] ?? null;
|
||||
|
||||
if($id !== null and !$force and isset($this->permanentWindows[$id])){
|
||||
throw new \BadMethodCallException("Cannot remove fixed window $id (" . get_class($inventory) . ") from " . $this->getName());
|
||||
throw new \InvalidArgumentException("Cannot remove fixed window $id (" . get_class($inventory) . ") from " . $this->getName());
|
||||
}
|
||||
|
||||
$inventory->close($this);
|
||||
@ -3877,9 +3950,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
||||
public function onChunkChanged(Chunk $chunk){
|
||||
if(isset($this->usedChunks[$hash = Level::chunkHash($chunk->getX(), $chunk->getZ())])){
|
||||
$this->usedChunks[$hash] = false;
|
||||
if(!$this->spawned){
|
||||
$this->nextChunkOrderRun = 0;
|
||||
}
|
||||
$this->nextChunkOrderRun = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace pocketmine {
|
||||
use pocketmine\wizard\SetupWizard;
|
||||
|
||||
const NAME = "PocketMine-MP";
|
||||
const BASE_VERSION = "3.4.0";
|
||||
const BASE_VERSION = "3.6.3";
|
||||
const IS_DEVELOPMENT_BUILD = false;
|
||||
const BUILD_NUMBER = 0;
|
||||
|
||||
@ -177,7 +177,6 @@ namespace pocketmine {
|
||||
ini_set("default_charset", "utf-8");
|
||||
|
||||
ini_set("memory_limit", '-1');
|
||||
define('pocketmine\START_TIME', microtime(true));
|
||||
|
||||
define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'src' . DIRECTORY_SEPARATOR . 'pocketmine' . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR);
|
||||
|
||||
@ -245,6 +244,8 @@ namespace pocketmine {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: move this to a Server field
|
||||
define('pocketmine\START_TIME', microtime(true));
|
||||
ThreadManager::init();
|
||||
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
|
||||
|
||||
|
@ -98,7 +98,6 @@ use pocketmine\tile\Tile;
|
||||
use pocketmine\timings\Timings;
|
||||
use pocketmine\timings\TimingsHandler;
|
||||
use pocketmine\updater\AutoUpdater;
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\Config;
|
||||
use pocketmine\utils\Internet;
|
||||
use pocketmine\utils\MainLogger;
|
||||
@ -106,6 +105,76 @@ use pocketmine\utils\Terminal;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\Utils;
|
||||
use pocketmine\utils\UUID;
|
||||
use function array_filter;
|
||||
use function array_key_exists;
|
||||
use function array_shift;
|
||||
use function array_sum;
|
||||
use function asort;
|
||||
use function assert;
|
||||
use function base64_encode;
|
||||
use function bin2hex;
|
||||
use function class_exists;
|
||||
use function count;
|
||||
use function define;
|
||||
use function explode;
|
||||
use function extension_loaded;
|
||||
use function file_exists;
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
use function filemtime;
|
||||
use function floor;
|
||||
use function function_exists;
|
||||
use function get_class;
|
||||
use function getmypid;
|
||||
use function getopt;
|
||||
use function gettype;
|
||||
use function implode;
|
||||
use function ini_get;
|
||||
use function ini_set;
|
||||
use function is_array;
|
||||
use function is_bool;
|
||||
use function is_dir;
|
||||
use function is_object;
|
||||
use function is_string;
|
||||
use function is_subclass_of;
|
||||
use function json_decode;
|
||||
use function max;
|
||||
use function microtime;
|
||||
use function min;
|
||||
use function mkdir;
|
||||
use function pcntl_signal;
|
||||
use function pcntl_signal_dispatch;
|
||||
use function preg_replace;
|
||||
use function random_bytes;
|
||||
use function random_int;
|
||||
use function realpath;
|
||||
use function register_shutdown_function;
|
||||
use function rename;
|
||||
use function round;
|
||||
use function scandir;
|
||||
use function sleep;
|
||||
use function spl_object_hash;
|
||||
use function sprintf;
|
||||
use function str_repeat;
|
||||
use function str_replace;
|
||||
use function stripos;
|
||||
use function strlen;
|
||||
use function strrpos;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
use function time;
|
||||
use function touch;
|
||||
use function trim;
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use const INT32_MAX;
|
||||
use const INT32_MIN;
|
||||
use const PHP_EOL;
|
||||
use const PHP_INT_MAX;
|
||||
use const PTHREADS_INHERIT_NONE;
|
||||
use const SCANDIR_SORT_NONE;
|
||||
use const SIGHUP;
|
||||
use const SIGINT;
|
||||
use const SIGTERM;
|
||||
|
||||
/**
|
||||
* The class that manages everything
|
||||
@ -1059,7 +1128,7 @@ class Server{
|
||||
return false;
|
||||
}
|
||||
|
||||
$seed = $seed ?? Binary::readInt(random_bytes(4));
|
||||
$seed = $seed ?? random_int(INT32_MIN, INT32_MAX);
|
||||
|
||||
if(!isset($options["preset"])){
|
||||
$options["preset"] = $this->getConfigString("generator-settings", "");
|
||||
@ -1449,8 +1518,6 @@ class Server{
|
||||
"announce-player-achievements" => true,
|
||||
"spawn-protection" => 16,
|
||||
"max-players" => 20,
|
||||
"spawn-animals" => true,
|
||||
"spawn-mobs" => true,
|
||||
"gamemode" => 0,
|
||||
"force-gamemode" => false,
|
||||
"hardcore" => false,
|
||||
@ -1485,7 +1552,7 @@ class Server{
|
||||
return;
|
||||
}
|
||||
|
||||
if(((int) ini_get('zend.assertions')) > 0 and ((bool) $this->getProperty("debug.assertions.warn-if-enabled", true)) !== false){
|
||||
if(((int) ini_get('zend.assertions')) !== -1){
|
||||
$this->logger->warning("Debugging assertions are enabled, this may impact on performance. To disable them, set `zend.assertions = -1` in php.ini.");
|
||||
}
|
||||
|
||||
@ -1663,7 +1730,9 @@ class Server{
|
||||
GeneratorManager::registerDefaultGenerators();
|
||||
|
||||
foreach((array) $this->getProperty("worlds", []) as $name => $options){
|
||||
if(!is_array($options)){
|
||||
if($options === null){
|
||||
$options = [];
|
||||
}elseif(!is_array($options)){
|
||||
continue;
|
||||
}
|
||||
if(!$this->loadLevel($name)){
|
||||
@ -2078,9 +2147,6 @@ class Server{
|
||||
$this->network->unregisterInterface($interface);
|
||||
}
|
||||
}
|
||||
|
||||
$this->getLogger()->debug("Collecting cycles");
|
||||
gc_collect_cycles();
|
||||
}catch(\Throwable $e){
|
||||
$this->logger->logException($e);
|
||||
$this->logger->emergency("Crashed while crashing, killing process");
|
||||
@ -2173,7 +2239,7 @@ class Server{
|
||||
"fullFile" => $e->getFile(),
|
||||
"file" => $errfile,
|
||||
"line" => $errline,
|
||||
"trace" => Utils::getTrace(0, $trace)
|
||||
"trace" => $trace
|
||||
];
|
||||
|
||||
global $lastExceptionError, $lastError;
|
||||
@ -2212,7 +2278,7 @@ class Server{
|
||||
if(is_string($plugin)){
|
||||
$p = $this->pluginManager->getPlugin($plugin);
|
||||
if($p instanceof Plugin and !($p->getPluginLoader() instanceof PharPluginLoader)){
|
||||
$report = false;
|
||||
$this->logger->debug("Not sending crashdump due to caused by non-phar plugin");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2254,6 +2320,7 @@ class Server{
|
||||
//Force minimum uptime to be >= 120 seconds, to reduce the impact of spammy crash loops
|
||||
$spacing = ((int) \pocketmine\START_TIME) - time() + 120;
|
||||
if($spacing > 0){
|
||||
echo "--- Waiting $spacing seconds to throttle automatic restart (you can kill the process safely now) ---" . PHP_EOL;
|
||||
sleep($spacing);
|
||||
}
|
||||
@Utils::kill(getmypid());
|
||||
@ -2491,9 +2558,7 @@ class Server{
|
||||
$this->logger->debug("Unhandled raw packet from $address $port: " . bin2hex($payload));
|
||||
}
|
||||
}catch(\Throwable $e){
|
||||
if(\pocketmine\DEBUG > 1){
|
||||
$this->logger->logException($e);
|
||||
}
|
||||
$this->logger->logException($e);
|
||||
|
||||
$this->getNetwork()->blockAddress($address, 600);
|
||||
}
|
||||
@ -2584,10 +2649,9 @@ class Server{
|
||||
|
||||
TimingsHandler::tick($this->currentTPS <= $this->profilingTickRate);
|
||||
|
||||
array_shift($this->tickAverage);
|
||||
$this->tickAverage[] = $this->currentTPS;
|
||||
array_shift($this->useAverage);
|
||||
$this->useAverage[] = $this->currentUse;
|
||||
$idx = $this->tickCounter % 20;
|
||||
$this->tickAverage[$idx] = $this->currentTPS;
|
||||
$this->useAverage[$idx] = $this->currentUse;
|
||||
|
||||
if(($this->nextTick - $tickTime) < -1){
|
||||
$this->nextTick = $tickTime;
|
||||
|
@ -28,7 +28,7 @@ namespace pocketmine;
|
||||
*/
|
||||
abstract class Thread extends \Thread{
|
||||
|
||||
/** @var \ClassLoader */
|
||||
/** @var \ClassLoader|null */
|
||||
protected $classLoader;
|
||||
/** @var string|null */
|
||||
protected $composerAutoloaderPath;
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine;
|
||||
|
||||
use pocketmine\utils\MainLogger;
|
||||
use function spl_object_hash;
|
||||
|
||||
class ThreadManager extends \Volatile{
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace pocketmine;
|
||||
*/
|
||||
abstract class Worker extends \Worker{
|
||||
|
||||
/** @var \ClassLoader */
|
||||
/** @var \ClassLoader|null */
|
||||
protected $classLoader;
|
||||
/** @var string|null */
|
||||
protected $composerAutoloaderPath;
|
||||
|
@ -26,6 +26,13 @@ namespace pocketmine\block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function array_map;
|
||||
use function array_reverse;
|
||||
use function array_search;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
|
||||
abstract class BaseRail extends Flowable{
|
||||
|
||||
@ -98,7 +105,7 @@ abstract class BaseRail extends Flowable{
|
||||
$meta = array_search(array_reverse($connections), $lookup, true);
|
||||
}
|
||||
if($meta === false){
|
||||
throw new \InvalidArgumentException("No meta value matches connections " . implode(", ", array_map('dechex', $connections)));
|
||||
throw new \InvalidArgumentException("No meta value matches connections " . implode(", ", array_map('\dechex', $connections)));
|
||||
}
|
||||
|
||||
return $meta;
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use function mt_rand;
|
||||
|
||||
class Beetroot extends Crops{
|
||||
|
||||
|
@ -38,6 +38,9 @@ use pocketmine\metadata\Metadatable;
|
||||
use pocketmine\metadata\MetadataValue;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use function array_merge;
|
||||
use function get_class;
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
@ -266,6 +269,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
* @param Item $item
|
||||
*
|
||||
* @return float
|
||||
* @throws \InvalidArgumentException if the item efficiency is not a positive number
|
||||
*/
|
||||
public function getBreakTime(Item $item) : float{
|
||||
$base = $this->getHardness();
|
||||
@ -277,7 +281,7 @@ class Block extends Position implements BlockIds, Metadatable{
|
||||
|
||||
$efficiency = $item->getMiningEfficiency($this);
|
||||
if($efficiency <= 0){
|
||||
throw new \RuntimeException("Item efficiency is invalid");
|
||||
throw new \InvalidArgumentException(get_class($item) . " has invalid mining efficiency: expected >= 0, got $efficiency");
|
||||
}
|
||||
|
||||
$base /= $efficiency;
|
||||
|
@ -25,6 +25,10 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Position;
|
||||
use function file_get_contents;
|
||||
use function json_decode;
|
||||
use function max;
|
||||
use function min;
|
||||
|
||||
/**
|
||||
* Manages block registration and instance creation
|
||||
@ -167,7 +171,7 @@ class BlockFactory{
|
||||
self::registerBlock(new Cake());
|
||||
//TODO: REPEATER_BLOCK
|
||||
//TODO: POWERED_REPEATER
|
||||
//TODO: INVISIBLEBEDROCK
|
||||
self::registerBlock(new InvisibleBedrock());
|
||||
self::registerBlock(new Trapdoor());
|
||||
//TODO: MONSTER_EGG
|
||||
self::registerBlock(new StoneBricks());
|
||||
@ -315,13 +319,13 @@ class BlockFactory{
|
||||
self::registerBlock(new Stonecutter());
|
||||
self::registerBlock(new GlowingObsidian());
|
||||
self::registerBlock(new NetherReactor());
|
||||
//TODO: INFO_UPDATE
|
||||
//TODO: INFO_UPDATE2
|
||||
self::registerBlock(new InfoUpdate(Block::INFO_UPDATE, 0, "update!"));
|
||||
self::registerBlock(new InfoUpdate(Block::INFO_UPDATE2, 0, "ate!upd"));
|
||||
//TODO: MOVINGBLOCK
|
||||
//TODO: OBSERVER
|
||||
//TODO: STRUCTURE_BLOCK
|
||||
|
||||
//TODO: RESERVED6
|
||||
self::registerBlock(new Reserved6(Block::RESERVED6, 0, "reserved6"));
|
||||
|
||||
for($id = 0, $size = self::$fullList->getSize() >> 4; $id < $size; ++$id){
|
||||
if(self::$fullList[$id << 4] === null){
|
||||
@ -426,8 +430,13 @@ class BlockFactory{
|
||||
public static function registerStaticRuntimeIdMappings() : void{
|
||||
/** @var mixed[] $runtimeIdMap */
|
||||
$runtimeIdMap = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "runtimeid_table.json"), true);
|
||||
$legacyIdMap = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "legacy_id_map.json"), true);
|
||||
foreach($runtimeIdMap as $k => $obj){
|
||||
self::registerMapping($k, $obj["id"], $obj["data"]);
|
||||
//this has to use the json offset to make sure the mapping is consistent with what we send over network, even though we aren't using all the entries
|
||||
if(!isset($legacyIdMap[$obj["name"]])){
|
||||
continue;
|
||||
}
|
||||
self::registerMapping($k, $legacyIdMap[$obj["name"]], $obj["data"]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use function mt_rand;
|
||||
|
||||
class BrownMushroomBlock extends RedMushroomBlock{
|
||||
|
||||
|
@ -96,9 +96,12 @@ class Cactus extends Transparent{
|
||||
if($b->getId() === self::AIR){
|
||||
$ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS));
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
|
||||
if($ev->isCancelled()){
|
||||
break;
|
||||
}
|
||||
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->meta = 0;
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use function mt_rand;
|
||||
|
||||
class Carrot extends Crops{
|
||||
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\TieredTool;
|
||||
use function mt_rand;
|
||||
|
||||
class CoalOre extends Solid{
|
||||
|
||||
|
@ -30,6 +30,18 @@ use pocketmine\math\Vector3;
|
||||
class CobblestoneWall extends Transparent{
|
||||
public const NONE_MOSSY_WALL = 0;
|
||||
public const MOSSY_WALL = 1;
|
||||
public const GRANITE_WALL = 2;
|
||||
public const DIORITE_WALL = 3;
|
||||
public const ANDESITE_WALL = 4;
|
||||
public const SANDSTONE_WALL = 5;
|
||||
public const BRICK_WALL = 6;
|
||||
public const STONE_BRICK_WALL = 7;
|
||||
public const MOSSY_STONE_BRICK_WALL = 8;
|
||||
public const NETHER_BRICK_WALL = 9;
|
||||
public const END_STONE_BRICK_WALL = 10;
|
||||
public const PRISMARINE_WALL = 11;
|
||||
public const RED_SANDSTONE_WALL = 12;
|
||||
public const RED_NETHER_BRICK_WALL = 13;
|
||||
|
||||
protected $id = self::COBBLESTONE_WALL;
|
||||
|
||||
@ -50,11 +62,23 @@ class CobblestoneWall extends Transparent{
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
if($this->meta === 0x01){
|
||||
return "Mossy Cobblestone Wall";
|
||||
}
|
||||
|
||||
return "Cobblestone Wall";
|
||||
static $names = [
|
||||
self::NONE_MOSSY_WALL => "Cobblestone",
|
||||
self::MOSSY_WALL => "Mossy Cobblestone",
|
||||
self::GRANITE_WALL => "Granite",
|
||||
self::DIORITE_WALL => "Diorite",
|
||||
self::ANDESITE_WALL => "Andesite",
|
||||
self::SANDSTONE_WALL => "Sandstone",
|
||||
self::BRICK_WALL => "Brick",
|
||||
self::STONE_BRICK_WALL => "Stone Brick",
|
||||
self::MOSSY_STONE_BRICK_WALL => "Mossy Stone Brick",
|
||||
self::NETHER_BRICK_WALL => "Nether Brick",
|
||||
self::END_STONE_BRICK_WALL => "End Stone Brick",
|
||||
self::PRISMARINE_WALL => "Prismarine",
|
||||
self::RED_SANDSTONE_WALL => "Red Sandstone",
|
||||
self::RED_NETHER_BRICK_WALL => "Red Nether Brick"
|
||||
];
|
||||
return ($names[$this->getVariant()] ?? "Unknown") . " Wall";
|
||||
}
|
||||
|
||||
protected function recalculateBoundingBox() : ?AxisAlignedBB{
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function mt_rand;
|
||||
|
||||
abstract class Crops extends Flowable{
|
||||
|
||||
@ -42,7 +43,7 @@ abstract class Crops extends Flowable{
|
||||
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
if($this->meta < 7 and $item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
|
||||
$block = clone $this;
|
||||
$block->meta += mt_rand(2, 5);
|
||||
if($block->meta > 7){
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function mt_rand;
|
||||
|
||||
class DeadBush extends Flowable{
|
||||
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\TieredTool;
|
||||
use function mt_rand;
|
||||
|
||||
class DiamondOre extends Solid{
|
||||
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function mt_rand;
|
||||
|
||||
class DoublePlant extends Flowable{
|
||||
public const BITFLAG_TOP = 0x08;
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\TieredTool;
|
||||
use function mt_rand;
|
||||
|
||||
class EmeraldOre extends Solid{
|
||||
|
||||
|
@ -31,6 +31,8 @@ use pocketmine\event\entity\EntityDamageByBlockEvent;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use function min;
|
||||
use function mt_rand;
|
||||
|
||||
class Fire extends Flowable{
|
||||
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use function mt_rand;
|
||||
|
||||
class Glowstone extends Transparent{
|
||||
|
||||
|
@ -32,6 +32,7 @@ use pocketmine\level\generator\object\TallGrass as TallGrassObject;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\Random;
|
||||
use function mt_rand;
|
||||
|
||||
class Grass extends Solid{
|
||||
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use function mt_rand;
|
||||
|
||||
class Gravel extends Fallable{
|
||||
|
||||
|
@ -56,7 +56,7 @@ class Ice extends Transparent{
|
||||
}
|
||||
|
||||
public function onBreak(Item $item, Player $player = null) : bool{
|
||||
if(!$item->hasEnchantment(Enchantment::SILK_TOUCH)){
|
||||
if(($player === null or $player->isSurvival()) and !$item->hasEnchantment(Enchantment::SILK_TOUCH)){
|
||||
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::WATER), true);
|
||||
}
|
||||
return parent::onBreak($item, $player);
|
||||
|
31
src/pocketmine/block/InfoUpdate.php
Normal file
31
src/pocketmine/block/InfoUpdate.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class InfoUpdate extends Solid{
|
||||
|
||||
public function getHardness() : float{
|
||||
return 1;
|
||||
}
|
||||
}
|
51
src/pocketmine/block/InvisibleBedrock.php
Normal file
51
src/pocketmine/block/InvisibleBedrock.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
||||
class InvisibleBedrock extends Transparent{
|
||||
|
||||
protected $id = self::INVISIBLE_BEDROCK;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "Invisible Bedrock";
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function getBlastResistance() : float{
|
||||
return 18000000;
|
||||
}
|
||||
|
||||
public function isBreakable(Item $item) : bool{
|
||||
return false;
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\ItemFrame as TileItemFrame;
|
||||
use pocketmine\tile\Tile;
|
||||
use function lcg_value;
|
||||
|
||||
class ItemFrame extends Flowable{
|
||||
protected $id = Block::ITEM_FRAME_BLOCK;
|
||||
@ -64,7 +65,7 @@ class ItemFrame extends Flowable{
|
||||
2 => Vector3::SIDE_NORTH,
|
||||
3 => Vector3::SIDE_SOUTH
|
||||
];
|
||||
if(!$this->getSide($sides[$this->meta])->isSolid()){
|
||||
if(isset($sides[$this->meta]) and !$this->getSide($sides[$this->meta])->isSolid()){
|
||||
$this->level->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
@ -111,4 +112,8 @@ class ItemFrame extends Flowable{
|
||||
public function isAffectedBySilkTouch() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0.25;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\TieredTool;
|
||||
use function mt_rand;
|
||||
|
||||
class LapisOre extends Solid{
|
||||
|
||||
|
@ -28,6 +28,7 @@ use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function mt_rand;
|
||||
|
||||
class Leaves extends Transparent{
|
||||
public const OAK = 0;
|
||||
|
@ -28,9 +28,12 @@ use pocketmine\event\block\BlockFormEvent;
|
||||
use pocketmine\event\block\BlockSpreadEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\sound\FizzSound;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
|
||||
use function array_fill;
|
||||
use function lcg_value;
|
||||
use function min;
|
||||
|
||||
abstract class Liquid extends Transparent{
|
||||
|
||||
@ -435,7 +438,7 @@ abstract class Liquid extends Transparent{
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->level->setBlock($this, $ev->getNewState(), true, true);
|
||||
$this->level->broadcastLevelSoundEvent($this->add(0.5, 0.5, 0.5), LevelSoundEventPacket::SOUND_FIZZ, (int) ((2.6 + (lcg_value() - lcg_value()) * 0.8) * 1000));
|
||||
$this->level->addSound(new FizzSound($this->add(0.5, 0.5, 0.5), 2.6 + (lcg_value() - lcg_value()) * 0.8));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use function mt_rand;
|
||||
|
||||
class Melon extends Transparent{
|
||||
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use function mt_rand;
|
||||
|
||||
class MelonStem extends Crops{
|
||||
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\TieredTool;
|
||||
use function mt_rand;
|
||||
|
||||
class MonsterSpawner extends Transparent{
|
||||
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\event\block\BlockSpreadEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use function mt_rand;
|
||||
|
||||
class Mycelium extends Solid{
|
||||
|
||||
|
@ -26,6 +26,7 @@ namespace pocketmine\block;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\TieredTool;
|
||||
use function mt_rand;
|
||||
|
||||
class NetherQuartzOre extends Solid{
|
||||
|
||||
|
@ -29,6 +29,7 @@ use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function mt_rand;
|
||||
|
||||
class NetherWartPlant extends Flowable{
|
||||
protected $id = Block::NETHER_WART_PLANT;
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use function mt_rand;
|
||||
|
||||
class Potato extends Crops{
|
||||
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\event\block\BlockGrowEvent;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use function mt_rand;
|
||||
|
||||
class PumpkinStem extends Crops{
|
||||
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use function mt_rand;
|
||||
|
||||
class RedMushroomBlock extends Solid{
|
||||
|
||||
|
@ -28,6 +28,7 @@ use pocketmine\item\ItemFactory;
|
||||
use pocketmine\item\TieredTool;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function mt_rand;
|
||||
|
||||
class RedstoneOre extends Solid{
|
||||
|
||||
|
31
src/pocketmine/block/Reserved6.php
Normal file
31
src/pocketmine/block/Reserved6.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* ____ _ _ __ __ _ __ __ ____
|
||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* @author PocketMine Team
|
||||
* @link http://www.pocketmine.net/
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block;
|
||||
|
||||
class Reserved6 extends Solid{
|
||||
|
||||
public function getHardness() : float{
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ use pocketmine\level\generator\object\Tree;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\Random;
|
||||
use function mt_rand;
|
||||
|
||||
class Sapling extends Flowable{
|
||||
public const OAK = 0;
|
||||
|
@ -29,6 +29,7 @@ use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\Sign as TileSign;
|
||||
use pocketmine\tile\Tile;
|
||||
use function floor;
|
||||
|
||||
class SignPost extends Transparent{
|
||||
|
||||
|
@ -89,7 +89,7 @@ abstract class Stair extends Transparent{
|
||||
2 => 1,
|
||||
3 => 3
|
||||
];
|
||||
$this->meta = $faces[$player->getDirection()] & 0x03;
|
||||
$this->meta = $player !== null ? $faces[$player->getDirection()] & 0x03 : 0;
|
||||
if(($clickVector->y > 0.5 and $face !== Vector3::SIDE_UP) or $face === Vector3::SIDE_DOWN){
|
||||
$this->meta |= 0x04; //Upside-down stairs
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\tile\Banner as TileBanner;
|
||||
use pocketmine\tile\Tile;
|
||||
use function floor;
|
||||
|
||||
class StandingBanner extends Transparent{
|
||||
|
||||
|
@ -26,6 +26,12 @@ namespace pocketmine\block;
|
||||
class StoneSlab2 extends StoneSlab{
|
||||
public const TYPE_RED_SANDSTONE = 0;
|
||||
public const TYPE_PURPUR = 1;
|
||||
public const TYPE_PRISMARINE = 2;
|
||||
public const TYPE_DARK_PRISMARINE = 3;
|
||||
public const TYPE_PRISMARINE_BRICKS = 4;
|
||||
public const TYPE_MOSSY_COBBLESTONE = 5;
|
||||
public const TYPE_SMOOTH_SANDSTONE = 6;
|
||||
public const TYPE_RED_NETHER_BRICK = 7;
|
||||
|
||||
protected $id = self::STONE_SLAB2;
|
||||
|
||||
@ -36,7 +42,13 @@ class StoneSlab2 extends StoneSlab{
|
||||
public function getName() : string{
|
||||
static $names = [
|
||||
self::TYPE_RED_SANDSTONE => "Red Sandstone",
|
||||
self::TYPE_PURPUR => "Purpur"
|
||||
self::TYPE_PURPUR => "Purpur",
|
||||
self::TYPE_PRISMARINE => "Prismarine",
|
||||
self::TYPE_DARK_PRISMARINE => "Dark Prismarine",
|
||||
self::TYPE_PRISMARINE_BRICKS => "Prismarine Bricks",
|
||||
self::TYPE_MOSSY_COBBLESTONE => "Mossy Cobblestone",
|
||||
self::TYPE_SMOOTH_SANDSTONE => "Smooth Sandstone",
|
||||
self::TYPE_RED_NETHER_BRICK => "Red Nether Brick"
|
||||
];
|
||||
|
||||
return (($this->meta & 0x08) > 0 ? "Upper " : "") . ($names[$this->getVariant()] ?? "") . " Slab";
|
||||
|
@ -50,9 +50,11 @@ class Sugarcane extends Flowable{
|
||||
if($b->getId() === self::AIR){
|
||||
$ev = new BlockGrowEvent($b, BlockFactory::get(Block::SUGARCANE_BLOCK));
|
||||
$ev->call();
|
||||
if(!$ev->isCancelled()){
|
||||
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
|
||||
if($ev->isCancelled()){
|
||||
break;
|
||||
}
|
||||
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +25,16 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\entity\Entity;
|
||||
use pocketmine\entity\projectile\Arrow;
|
||||
use pocketmine\item\Durable;
|
||||
use pocketmine\item\enchantment\Enchantment;
|
||||
use pocketmine\item\FlintSteel;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\Random;
|
||||
use function cos;
|
||||
use function sin;
|
||||
use const M_PI;
|
||||
|
||||
class TNT extends Solid{
|
||||
|
||||
@ -48,8 +53,10 @@ class TNT extends Solid{
|
||||
}
|
||||
|
||||
public function onActivate(Item $item, Player $player = null) : bool{
|
||||
if($item instanceof FlintSteel){
|
||||
$item->applyDamage(1);
|
||||
if($item instanceof FlintSteel or $item->hasEnchantment(Enchantment::FIRE_ASPECT)){
|
||||
if($item instanceof Durable){
|
||||
$item->applyDamage(1);
|
||||
}
|
||||
$this->ignite();
|
||||
return true;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function mt_rand;
|
||||
|
||||
class TallGrass extends Flowable{
|
||||
|
||||
@ -50,8 +51,8 @@ class TallGrass extends Flowable{
|
||||
}
|
||||
|
||||
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN);
|
||||
if($down->getId() === self::GRASS){
|
||||
$down = $this->getSide(Vector3::SIDE_DOWN)->getId();
|
||||
if($down === self::GRASS or $down === self::DIRT){
|
||||
$this->getLevel()->setBlock($blockReplace, $this, true);
|
||||
|
||||
return true;
|
||||
|
@ -45,8 +45,8 @@ class Torch extends Flowable{
|
||||
|
||||
public function onNearbyBlockChange() : void{
|
||||
$below = $this->getSide(Vector3::SIDE_DOWN);
|
||||
$side = $this->getDamage();
|
||||
$faces = [
|
||||
$meta = $this->getDamage();
|
||||
static $faces = [
|
||||
0 => Vector3::SIDE_DOWN,
|
||||
1 => Vector3::SIDE_WEST,
|
||||
2 => Vector3::SIDE_EAST,
|
||||
@ -54,8 +54,9 @@ class Torch extends Flowable{
|
||||
4 => Vector3::SIDE_SOUTH,
|
||||
5 => Vector3::SIDE_DOWN
|
||||
];
|
||||
$face = $faces[$meta] ?? Vector3::SIDE_DOWN;
|
||||
|
||||
if($this->getSide($faces[$side])->isTransparent() and !($faces[$side] === Vector3::SIDE_DOWN and ($below->getId() === self::FENCE or $below->getId() === self::COBBLESTONE_WALL))){
|
||||
if($this->getSide($face)->isTransparent() and !($face === Vector3::SIDE_DOWN and ($below->getId() === self::FENCE or $below->getId() === self::COBBLESTONE_WALL))){
|
||||
$this->getLevel()->useBreakOn($this);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,10 @@ class UnknownBlock extends Transparent{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function canBePlaced() : bool{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getDrops(Item $item) : array{
|
||||
return [];
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ use pocketmine\item\Item;
|
||||
use pocketmine\math\AxisAlignedBB;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use function max;
|
||||
use function min;
|
||||
|
||||
class Vine extends Flowable{
|
||||
public const FLAG_SOUTH = 0x01;
|
||||
|
@ -67,7 +67,7 @@ class Water extends Liquid{
|
||||
|
||||
public function onEntityCollide(Entity $entity) : void{
|
||||
$entity->resetFallDistance();
|
||||
if($entity->fireTicks > 0){
|
||||
if($entity->isOnFire()){
|
||||
$entity->extinguish();
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ namespace pocketmine\block;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use function mt_rand;
|
||||
|
||||
class Wheat extends Crops{
|
||||
|
||||
|
@ -26,12 +26,15 @@ declare(strict_types=1);
|
||||
*/
|
||||
namespace pocketmine\command;
|
||||
|
||||
use pocketmine\command\utils\CommandException;
|
||||
use pocketmine\lang\TextContainer;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\permission\PermissionManager;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\timings\TimingsHandler;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function explode;
|
||||
use function str_replace;
|
||||
|
||||
abstract class Command{
|
||||
|
||||
@ -90,6 +93,7 @@ abstract class Command{
|
||||
* @param string[] $args
|
||||
*
|
||||
* @return mixed
|
||||
* @throws CommandException
|
||||
*/
|
||||
abstract public function execute(CommandSender $sender, string $commandLabel, array $args);
|
||||
|
||||
|
@ -26,6 +26,22 @@ namespace pocketmine\command;
|
||||
use pocketmine\snooze\SleeperNotifier;
|
||||
use pocketmine\Thread;
|
||||
use pocketmine\utils\Utils;
|
||||
use function extension_loaded;
|
||||
use function fclose;
|
||||
use function fgets;
|
||||
use function fopen;
|
||||
use function fstat;
|
||||
use function getopt;
|
||||
use function is_resource;
|
||||
use function microtime;
|
||||
use function preg_replace;
|
||||
use function readline;
|
||||
use function readline_add_history;
|
||||
use function stream_isatty;
|
||||
use function stream_select;
|
||||
use function trim;
|
||||
use function usleep;
|
||||
use const STDIN;
|
||||
|
||||
class CommandReader extends Thread{
|
||||
|
||||
|
@ -31,6 +31,9 @@ use pocketmine\permission\PermissionAttachmentInfo;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\MainLogger;
|
||||
use function explode;
|
||||
use function trim;
|
||||
use const PHP_INT_MAX;
|
||||
|
||||
class ConsoleCommandSender implements CommandSender{
|
||||
|
||||
|
@ -25,6 +25,11 @@ namespace pocketmine\command;
|
||||
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function ord;
|
||||
use function strlen;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
|
||||
class FormattedCommandAlias extends Command{
|
||||
private $formatStrings = [];
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\command;
|
||||
|
||||
use pocketmine\lang\TextContainer;
|
||||
use function trim;
|
||||
|
||||
class RemoteConsoleCommandSender extends ConsoleCommandSender{
|
||||
|
||||
|
@ -66,6 +66,16 @@ use pocketmine\command\defaults\VersionCommand;
|
||||
use pocketmine\command\defaults\WhitelistCommand;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\Server;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function min;
|
||||
use function preg_match_all;
|
||||
use function stripslashes;
|
||||
use function strpos;
|
||||
use function strtolower;
|
||||
use function trim;
|
||||
|
||||
class SimpleCommandMap implements CommandMap{
|
||||
|
||||
@ -90,9 +100,11 @@ class SimpleCommandMap implements CommandMap{
|
||||
new DefaultGamemodeCommand("defaultgamemode"),
|
||||
new DeopCommand("deop"),
|
||||
new DifficultyCommand("difficulty"),
|
||||
new DumpMemoryCommand("dumpmemory"),
|
||||
new EffectCommand("effect"),
|
||||
new EnchantCommand("enchant"),
|
||||
new GamemodeCommand("gamemode"),
|
||||
new GarbageCollectorCommand("gc"),
|
||||
new GiveCommand("give"),
|
||||
new HelpCommand("help"),
|
||||
new KickCommand("kick"),
|
||||
@ -112,6 +124,7 @@ class SimpleCommandMap implements CommandMap{
|
||||
new SeedCommand("seed"),
|
||||
new SetWorldSpawnCommand("setworldspawn"),
|
||||
new SpawnpointCommand("spawnpoint"),
|
||||
new StatusCommand("status"),
|
||||
new StopCommand("stop"),
|
||||
new TeleportCommand("tp"),
|
||||
new TellCommand("tell"),
|
||||
@ -122,14 +135,6 @@ class SimpleCommandMap implements CommandMap{
|
||||
new VersionCommand("version"),
|
||||
new WhitelistCommand("whitelist")
|
||||
]);
|
||||
|
||||
if($this->server->getProperty("debug.commands", false)){
|
||||
$this->registerAll("pocketmine", [
|
||||
new StatusCommand("status"),
|
||||
new GarbageCollectorCommand("gc"),
|
||||
new DumpMemoryCommand("dumpmemory")
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -242,7 +247,16 @@ class SimpleCommandMap implements CommandMap{
|
||||
}
|
||||
|
||||
public function dispatch(CommandSender $sender, string $commandLine) : bool{
|
||||
$args = array_map("stripslashes", str_getcsv($commandLine, " "));
|
||||
$args = [];
|
||||
preg_match_all('/"((?:\\\\.|[^\\\\"])*)"|(\S+)/u', $commandLine, $matches);
|
||||
foreach($matches[0] as $k => $_){
|
||||
for($i = 1; $i <= 2; ++$i){
|
||||
if($matches[$i][$k] !== ""){
|
||||
$args[$k] = stripslashes($matches[$i][$k]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$sentCommandLabel = "";
|
||||
$target = $this->matchCommand($sentCommandLabel, $args);
|
||||
|
||||
|
@ -28,6 +28,9 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Player;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class BanCommand extends VanillaCommand{
|
||||
|
||||
|
@ -28,6 +28,10 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Player;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function preg_match;
|
||||
|
||||
class BanIpCommand extends VanillaCommand{
|
||||
|
||||
|
@ -27,6 +27,10 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\permission\BanEntry;
|
||||
use function array_map;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function strtolower;
|
||||
|
||||
class BanListCommand extends VanillaCommand{
|
||||
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Server;
|
||||
use function count;
|
||||
|
||||
class DefaultGamemodeCommand extends VanillaCommand{
|
||||
|
||||
|
@ -29,6 +29,8 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
|
||||
class DeopCommand extends VanillaCommand{
|
||||
|
||||
@ -51,6 +53,9 @@ class DeopCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
$name = array_shift($args);
|
||||
if(!Player::isValidUserName($name)){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player = $sender->getServer()->getOfflinePlayer($name);
|
||||
$player->setOp(false);
|
||||
|
@ -28,6 +28,7 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\level\Level;
|
||||
use function count;
|
||||
|
||||
class DifficultyCommand extends VanillaCommand{
|
||||
|
||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use function date;
|
||||
|
||||
class DumpMemoryCommand extends VanillaCommand{
|
||||
|
||||
|
@ -29,6 +29,9 @@ use pocketmine\entity\Effect;
|
||||
use pocketmine\entity\EffectInstance;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function strtolower;
|
||||
use const INT32_MAX;
|
||||
|
||||
class EffectCommand extends VanillaCommand{
|
||||
|
||||
@ -80,7 +83,7 @@ class EffectCommand extends VanillaCommand{
|
||||
$amplification = 0;
|
||||
|
||||
if(count($args) >= 3){
|
||||
if(($d = $this->getBoundedInt($sender, $args[2], 0, INT32_MAX)) === null){
|
||||
if(($d = $this->getBoundedInt($sender, $args[2], 0, (int) (INT32_MAX / 20))) === null){
|
||||
return false;
|
||||
}
|
||||
$duration = $d * 20; //ticks
|
||||
|
@ -29,6 +29,8 @@ use pocketmine\item\enchantment\Enchantment;
|
||||
use pocketmine\item\enchantment\EnchantmentInstance;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function is_numeric;
|
||||
|
||||
class EnchantCommand extends VanillaCommand{
|
||||
|
||||
@ -75,7 +77,15 @@ class EnchantCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
$item->addEnchantment(new EnchantmentInstance($enchantment, (int) ($args[2] ?? 1)));
|
||||
$level = 1;
|
||||
if(isset($args[2])){
|
||||
$level = $this->getBoundedInt($sender, $args[2], 1, $enchantment->getMaxLevel());
|
||||
if($level === null){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$item->addEnchantment(new EnchantmentInstance($enchantment, $level));
|
||||
$player->getInventory()->setItemInHand($item);
|
||||
|
||||
|
||||
|
@ -30,6 +30,7 @@ use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
|
||||
class GamemodeCommand extends VanillaCommand{
|
||||
|
||||
|
@ -25,6 +25,10 @@ namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function memory_get_usage;
|
||||
use function number_format;
|
||||
use function round;
|
||||
|
||||
class GarbageCollectorCommand extends VanillaCommand{
|
||||
|
||||
@ -66,7 +70,7 @@ class GarbageCollectorCommand extends VanillaCommand{
|
||||
$sender->sendMessage(TextFormat::GOLD . "Tiles: " . TextFormat::RED . number_format($tilesCollected));
|
||||
|
||||
$sender->sendMessage(TextFormat::GOLD . "Cycles: " . TextFormat::RED . number_format($cyclesCollected));
|
||||
$sender->sendMessage(TextFormat::GOLD . "Memory freed: " . TextFormat::RED . number_format(round((($memory - memory_get_usage()) / 1024) / 1024, 2)) . " MB");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Memory freed: " . TextFormat::RED . number_format(round((($memory - memory_get_usage()) / 1024) / 1024, 2), 2) . " MB");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,9 @@ use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\nbt\JsonNbtParser;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_slice;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class GiveCommand extends VanillaCommand{
|
||||
|
||||
|
@ -27,6 +27,17 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_chunk;
|
||||
use function array_pop;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function implode;
|
||||
use function is_numeric;
|
||||
use function ksort;
|
||||
use function min;
|
||||
use function strtolower;
|
||||
use const SORT_FLAG_CASE;
|
||||
use const SORT_NATURAL;
|
||||
|
||||
class HelpCommand extends VanillaCommand{
|
||||
|
||||
|
@ -29,6 +29,10 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function trim;
|
||||
|
||||
class KickCommand extends VanillaCommand{
|
||||
|
||||
|
@ -30,6 +30,7 @@ use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
|
||||
class KillCommand extends VanillaCommand{
|
||||
|
||||
|
@ -26,6 +26,10 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Player;
|
||||
use function array_filter;
|
||||
use function array_map;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class ListCommand extends VanillaCommand{
|
||||
|
||||
|
@ -28,6 +28,8 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class MeCommand extends VanillaCommand{
|
||||
|
||||
|
@ -29,6 +29,8 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
|
||||
class OpCommand extends VanillaCommand{
|
||||
|
||||
@ -51,6 +53,9 @@ class OpCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
$name = array_shift($args);
|
||||
if(!Player::isValidUserName($name)){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
$player = $sender->getServer()->getOfflinePlayer($name);
|
||||
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.op.success", [$player->getName()]));
|
||||
|
@ -27,6 +27,7 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use function count;
|
||||
|
||||
class PardonCommand extends VanillaCommand{
|
||||
|
||||
|
@ -27,6 +27,8 @@ use pocketmine\command\Command;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use function count;
|
||||
use function preg_match;
|
||||
|
||||
class PardonIpCommand extends VanillaCommand{
|
||||
|
||||
|
@ -29,6 +29,7 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemFactory;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\level\particle\AngryVillagerParticle;
|
||||
use pocketmine\level\particle\BlockForceFieldParticle;
|
||||
use pocketmine\level\particle\BubbleParticle;
|
||||
@ -61,6 +62,13 @@ use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\Random;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function max;
|
||||
use function microtime;
|
||||
use function mt_rand;
|
||||
use function strpos;
|
||||
use function strtolower;
|
||||
|
||||
class ParticleCommand extends VanillaCommand{
|
||||
|
||||
@ -84,14 +92,18 @@ class ParticleCommand extends VanillaCommand{
|
||||
|
||||
if($sender instanceof Player){
|
||||
$level = $sender->getLevel();
|
||||
$pos = new Vector3(
|
||||
$this->getRelativeDouble($sender->getX(), $sender, $args[1]),
|
||||
$this->getRelativeDouble($sender->getY(), $sender, $args[2], 0, Level::Y_MAX),
|
||||
$this->getRelativeDouble($sender->getZ(), $sender, $args[3])
|
||||
);
|
||||
}else{
|
||||
$level = $sender->getServer()->getDefaultLevel();
|
||||
$pos = new Vector3((float) $args[1], (float) $args[2], (float) $args[3]);
|
||||
}
|
||||
|
||||
$name = strtolower($args[0]);
|
||||
|
||||
$pos = new Vector3((float) $args[1], (float) $args[2], (float) $args[3]);
|
||||
|
||||
$xd = (float) $args[4];
|
||||
$yd = (float) $args[5];
|
||||
$zd = (float) $args[6];
|
||||
@ -211,12 +223,12 @@ class ParticleCommand extends VanillaCommand{
|
||||
}elseif(strpos($name, "blockcrack_") === 0){
|
||||
$d = explode("_", $name);
|
||||
if(count($d) === 2){
|
||||
return new TerrainParticle($pos, BlockFactory::get($d[1] & 0xff, $d[1] >> 12));
|
||||
return new TerrainParticle($pos, BlockFactory::get(((int) $d[1]) & 0xff, ((int) $d[1]) >> 12));
|
||||
}
|
||||
}elseif(strpos($name, "blockdust_") === 0){
|
||||
$d = explode("_", $name);
|
||||
if(count($d) >= 4){
|
||||
return new DustParticle($pos, $d[1] & 0xff, $d[2] & 0xff, $d[3] & 0xff, isset($d[4]) ? $d[4] & 0xff : 255);
|
||||
return new DustParticle($pos, ((int) $d[1]) & 0xff, ((int) $d[2]) & 0xff, ((int) $d[3]) & 0xff, isset($d[4]) ? ((int) $d[4]) & 0xff : 255);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,9 @@ use pocketmine\command\CommandSender;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\plugin\Plugin;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_map;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class PluginsCommand extends VanillaCommand{
|
||||
|
||||
|
@ -29,6 +29,8 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class SayCommand extends VanillaCommand{
|
||||
|
||||
|
@ -30,6 +30,8 @@ use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function round;
|
||||
|
||||
class SetWorldSpawnCommand extends VanillaCommand{
|
||||
|
||||
|
@ -31,6 +31,8 @@ use pocketmine\level\Level;
|
||||
use pocketmine\level\Position;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
use function round;
|
||||
|
||||
class SpawnpointCommand extends VanillaCommand{
|
||||
|
||||
|
@ -26,6 +26,11 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use pocketmine\utils\Utils;
|
||||
use function count;
|
||||
use function floor;
|
||||
use function microtime;
|
||||
use function number_format;
|
||||
use function round;
|
||||
|
||||
class StatusCommand extends VanillaCommand{
|
||||
|
||||
@ -91,14 +96,14 @@ class StatusCommand extends VanillaCommand{
|
||||
|
||||
$sender->sendMessage(TextFormat::GOLD . "Thread count: " . TextFormat::RED . Utils::getThreadCount());
|
||||
|
||||
$sender->sendMessage(TextFormat::GOLD . "Main thread memory: " . TextFormat::RED . number_format(round(($mUsage[0] / 1024) / 1024, 2)) . " MB.");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Total memory: " . TextFormat::RED . number_format(round(($mUsage[1] / 1024) / 1024, 2)) . " MB.");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Total virtual memory: " . TextFormat::RED . number_format(round(($mUsage[2] / 1024) / 1024, 2)) . " MB.");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Heap memory: " . TextFormat::RED . number_format(round(($rUsage[0] / 1024) / 1024, 2)) . " MB.");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Maximum memory (system): " . TextFormat::RED . number_format(round(($mUsage[2] / 1024) / 1024, 2)) . " MB.");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Main thread memory: " . TextFormat::RED . number_format(round(($mUsage[0] / 1024) / 1024, 2), 2) . " MB.");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Total memory: " . TextFormat::RED . number_format(round(($mUsage[1] / 1024) / 1024, 2), 2) . " MB.");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Total virtual memory: " . TextFormat::RED . number_format(round(($mUsage[2] / 1024) / 1024, 2), 2) . " MB.");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Heap memory: " . TextFormat::RED . number_format(round(($rUsage[0] / 1024) / 1024, 2), 2) . " MB.");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Maximum memory (system): " . TextFormat::RED . number_format(round(($mUsage[2] / 1024) / 1024, 2), 2) . " MB.");
|
||||
|
||||
if($server->getProperty("memory.global-limit") > 0){
|
||||
$sender->sendMessage(TextFormat::GOLD . "Maximum memory (manager): " . TextFormat::RED . number_format(round($server->getProperty("memory.global-limit"), 2)) . " MB.");
|
||||
$sender->sendMessage(TextFormat::GOLD . "Maximum memory (manager): " . TextFormat::RED . number_format(round($server->getProperty("memory.global-limit"), 2), 2) . " MB.");
|
||||
}
|
||||
|
||||
foreach($server->getLevels() as $level){
|
||||
|
@ -30,6 +30,10 @@ use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_filter;
|
||||
use function array_values;
|
||||
use function count;
|
||||
use function round;
|
||||
|
||||
class TeleportCommand extends VanillaCommand{
|
||||
|
||||
|
@ -28,6 +28,9 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function array_shift;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class TellCommand extends VanillaCommand{
|
||||
|
||||
|
@ -30,6 +30,7 @@ use pocketmine\lang\TranslationContainer;
|
||||
use pocketmine\level\Level;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\utils\TextFormat;
|
||||
use function count;
|
||||
|
||||
class TimeCommand extends VanillaCommand{
|
||||
|
||||
@ -54,9 +55,7 @@ class TimeCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
foreach($sender->getServer()->getLevels() as $level){
|
||||
$level->checkTime();
|
||||
$level->startTime();
|
||||
$level->checkTime();
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, "Restarted the time");
|
||||
return true;
|
||||
@ -67,9 +66,7 @@ class TimeCommand extends VanillaCommand{
|
||||
return true;
|
||||
}
|
||||
foreach($sender->getServer()->getLevels() as $level){
|
||||
$level->checkTime();
|
||||
$level->stopTime();
|
||||
$level->checkTime();
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, "Stopped the time");
|
||||
return true;
|
||||
@ -109,9 +106,7 @@ class TimeCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
foreach($sender->getServer()->getLevels() as $level){
|
||||
$level->checkTime();
|
||||
$level->setTime($value);
|
||||
$level->checkTime();
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.time.set", [$value]));
|
||||
}elseif($args[0] === "add"){
|
||||
@ -123,9 +118,7 @@ class TimeCommand extends VanillaCommand{
|
||||
|
||||
$value = $this->getInteger($sender, $args[1], 0);
|
||||
foreach($sender->getServer()->getLevels() as $level){
|
||||
$level->checkTime();
|
||||
$level->setTime($level->getTime() + $value);
|
||||
$level->checkTime();
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.time.added", [$value]));
|
||||
}else{
|
||||
|
@ -31,6 +31,22 @@ use pocketmine\scheduler\BulkCurlTask;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\timings\TimingsHandler;
|
||||
use pocketmine\utils\InternetException;
|
||||
use function count;
|
||||
use function fclose;
|
||||
use function file_exists;
|
||||
use function fopen;
|
||||
use function fseek;
|
||||
use function http_build_query;
|
||||
use function is_array;
|
||||
use function json_decode;
|
||||
use function mkdir;
|
||||
use function stream_get_contents;
|
||||
use function strtolower;
|
||||
use const CURLOPT_AUTOREFERER;
|
||||
use const CURLOPT_FOLLOWLOCATION;
|
||||
use const CURLOPT_HTTPHEADER;
|
||||
use const CURLOPT_POST;
|
||||
use const CURLOPT_POSTFIELDS;
|
||||
|
||||
class TimingsCommand extends VanillaCommand{
|
||||
|
||||
|
@ -26,6 +26,9 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\lang\TranslationContainer;
|
||||
use function array_slice;
|
||||
use function count;
|
||||
use function implode;
|
||||
|
||||
class TitleCommand extends VanillaCommand{
|
||||
|
||||
@ -82,7 +85,7 @@ class TitleCommand extends VanillaCommand{
|
||||
$player->addActionBarMessage(implode(" ", array_slice($args, 2)));
|
||||
break;
|
||||
case "times":
|
||||
if(count($args) < 4){
|
||||
if(count($args) < 5){
|
||||
throw new InvalidCommandSyntaxException();
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ namespace pocketmine\command\defaults;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\command\utils\InvalidCommandSyntaxException;
|
||||
use pocketmine\Player;
|
||||
use function count;
|
||||
|
||||
class TransferServerCommand extends VanillaCommand{
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user