Compare commits

...

475 Commits
3.2.1 ... 3.6.2

Author SHA1 Message Date
a8dab25201 Release 3.6.2 2019-02-14 17:15:19 +00:00
3de2b7969e Merge branch '3.5' into 3.6 2019-02-14 17:14:59 +00:00
8f486ea65d 3.5.13 is next 2019-02-14 17:14:34 +00:00
6b971b1761 Release 3.5.12 2019-02-14 16:55:44 +00:00
6f36fa504b TextFormat: make clean() less confusing, deduplicate some regex 2019-02-14 16:52:39 +00:00
8e73842a93 Player: work around 1.9 command casing crash bug, closes #2761 2019-02-14 16:17:17 +00:00
e71e18fc88 Merge branch '3.5' into 3.6 2019-02-14 16:02:30 +00:00
e1bacb5c6d Human: fixed hunger underflow when value is a fraction, closes #2761 2019-02-14 16:01:25 +00:00
44697e784a Sign: add validity checks on text encoding, scrub invalid UTF-8 on load
this works around a bug where corrupted text on preexisting signs can mess up the client. This also prevents corrupted text getting onto signs in the future by having them scrubbed and validated before applying them.
2019-02-14 15:16:51 +00:00
65529ff2ce Command: add @throws CommandException 2019-02-14 15:09:41 +00:00
c346c45d42 Use regex for command argument parsing, fixes #2266
moral of the story: don't abuse functions for things they weren't designed for... lol
2019-02-14 15:07:58 +00:00
c433fad0a7 another /u modifier 2019-02-14 13:50:56 +00:00
8fad5a6e30 TextFormat: use mb_scrub() in clean()
this redacts invalid characters to prevent them appearing in places that might break the client.
2019-02-13 20:01:36 +00:00
7a6f279825 TextFormat: fixed clean() not being unicode-aware 2019-02-13 17:06:44 +00:00
10b72c895d Merge branch '3.5' into 3.6 2019-02-13 14:53:00 +00:00
d520928888 Fixed startup time measurement, closes #2713, closes #2750 2019-02-13 14:50:52 +00:00
27767e7ddb Verify player name command input, closes #2729, closes #2749 2019-02-13 14:50:43 +00:00
243c12de7c EffectCommand: fix bounds check, closes #2055 2019-02-13 14:37:40 +00:00
372545e47e Merge branch '3.5' into 3.6 2019-02-12 16:56:53 +00:00
8913b48700 "Implement" info-update and reserved6 2019-02-12 16:56:12 +00:00
6ee4a0e090 Implement invisible bedrock to fix placement issues
I don't know why this wasn't done a long time ago, but here it is.
2019-02-12 16:41:23 +00:00
8bd8da4bc6 Merge branch '3.5' into 3.6 2019-02-10 17:15:48 +00:00
9ba4144a71 Server: remove useless gc_collect_cycles()
the server is shutting down at this point so who cares if there are cycles...
2019-02-10 17:15:41 +00:00
9da7c6af27 new metadata properties 2019-02-10 13:59:21 +00:00
109312284c 3.6.2 is next 2019-02-08 16:41:10 +00:00
51934614bc Release 3.6.1 2019-02-08 16:40:38 +00:00
9e89f65094 Fixed handling for some new blocks which slipped through the frontline 2019-02-08 16:38:17 +00:00
9562711b84 Updated BedrockData submodule to 1.9.0 2019-02-08 15:32:57 +00:00
30b49e0d22 Merge branch '3.5' into 3.6 2019-02-08 15:32:20 +00:00
a975868fc3 3.5.12 is next 2019-02-08 13:52:31 +00:00
b38b932845 Release 3.5.11 2019-02-08 13:52:09 +00:00
43cb19ebca Updated bedrockData submodule to 1.8.0 2019-02-08 13:51:41 +00:00
769cc91543 ItemFactory: fix crash when getting negative item IDs
these are now treated the same as any unknown item, and are now not possible to place.
2019-02-08 13:51:41 +00:00
278f37d3e0 3.6.1 is next 2019-02-07 22:07:31 +00:00
02a6ca84a9 Releass 3.6.0 2019-02-07 22:06:33 +00:00
b8703d5dff Protocol changes for 1.9.0 2019-02-07 21:56:42 +00:00
37c2d78731 3.5.11 is next 2019-02-07 20:47:05 +00:00
b7663e5815 Release 3.5.10 2019-02-07 20:46:27 +00:00
1d0ffa06f8 TallGrass: fixed placement on dirt, closes #2552 2019-02-07 16:55:25 +00:00
768cfe3953 Updated composer dependencies 2019-02-07 16:47:16 +00:00
2822465f33 Updated submodules 2019-02-07 16:20:45 +00:00
5da48f429f Fixed some remaining one-line field declarations, added type docs 2019-02-05 14:03:27 +00:00
dbd0d04549 fix wrong doc comments in Thread & Worker 2019-02-05 13:58:18 +00:00
0f92ec6d2a Level: Record a debug message when chunks are loaded without loaders 2019-02-03 16:24:10 +00:00
791b4d8ef3 SplashPotion: measure distance from eye height instead of base
this fixes effect durations being off (mostly), closes #2650
there are still some minor differences, but this is closer matching than the previous version.
2019-02-03 11:32:47 +00:00
0b7ff6f2e7 Level: properly mark some functions as @internal
this ensures these functions won't appear in the documentation.
2019-02-01 14:33:06 +00:00
af092b01e1 3.5.10 is next 2019-01-31 18:47:57 +00:00
d811217755 Release 3.5.9 2019-01-31 18:47:32 +00:00
d7f86f0240 Hack for client side regeneration (disable natural regeneration gamerule) (#2722) 2019-01-31 18:45:25 +00:00
5fe1d2e396 Level: fixed setChunk() bug introduced by eebd90ec42
Anyone who is using getChunkPlayers() should probably check that their code is actually doing what they think it's doing.
2019-01-31 18:28:42 +00:00
ddbb5363ef Block->getBreakTime() now throws InvalidArgumentException on items with bad efficiency values 2019-01-30 19:10:24 +00:00
d3704bfae4 3.5.9 is next 2019-01-30 12:49:46 +00:00
07f034d2da Release 3.5.8 2019-01-30 12:49:16 +00:00
331ae5498f Crash the generator when encountering invalid presets
this is a partial fix for #2717, but still not ideal because it'll spam whenever a chunk is attempted to be generated. However, fixing this properly requires potentially breaking API changes.
2019-01-30 12:29:04 +00:00
eebd90ec42 Level: fixed setChunk() leaking memory when not copying tiles/entities
closes #2719
2019-01-30 10:58:35 +00:00
8e47a40b4c Level: rename poorly-named parameter of setChunk()
this now has a mouthful of a name. I'd like to invert it, but I can't do that without silently breaking backwards compatibility, which is unacceptable.
2019-01-30 10:26:18 +00:00
0f9fdf6442 Fixed Cactus and Sugarcane growing through bad blocks
closes #2714
2019-01-29 17:32:48 +00:00
5364e4de68 Explosion: fix chest unpairing (root cause of #2701)
not ready to call this "fixed" yet because any chests that were already affected by the bug will still be affected. This change will prevent the creation of more broken chests like this.
2019-01-29 13:58:47 +00:00
1099e2044b SetupWizard: fixed user being able to avoid agreeing to license, closes #2703 2019-01-29 13:43:13 +00:00
80d48161d3 Crops: fixed consuming bonemeal on fully-grown crop, closes #2704 2019-01-29 13:41:02 +00:00
fbe8485696 Player: fixed falling causing starvation, closes #2708 2019-01-29 13:36:24 +00:00
a150f39b02 Fixed fall handling when flying, closes #2709 2019-01-29 13:28:43 +00:00
71d17c50d6 Fixed internal IP detection (#2711), closes #2702 2019-01-29 12:51:53 +00:00
3a18bdd6a0 Prevent block-picking unknown blocks 2019-01-28 17:45:48 +00:00
96857c65b6 Player: Fixed subscribing to broadcast permissions too early
Plugins would indirectly trigger permissible recalculation too early in the login sequence, which then caused their permissions to be recalculated and subscribing them to the broadcast permission far too early.
2019-01-27 15:08:08 +00:00
9826abd83e Stair: fixed crash if player is null 2019-01-26 16:59:03 +00:00
48c8c2a8c3 ItemFrame: address crashdump 2113950
thanks Mojang for designing this lovely system where so much undefined behaviour is able to take place :(
2019-01-26 16:58:25 +00:00
c83b7d9b69 Utils: fixed getNiceClosureName() not processing namespaced closures properly 2019-01-26 12:08:07 +00:00
c66dc7b273 Level: Optimize blockticking coordinate selection
generating 1 large bounded random costs the same as generating 4 small ones, so it makes more sense to do it like this instead.

Note that prior to 7.1 this code would not work due to it not handling 64-bit appropriately.
2019-01-25 19:43:16 +00:00
5bf7350ee5 Level: change some stupid var names 2019-01-25 17:10:44 +00:00
636cc1c199 Level: some mitigations for #2675
this reduces the performance impact by using smaller keys, which reduces the key distance for nearby blocks.
2019-01-25 13:17:33 +00:00
62b6405371 Use 2 space indents in YAML files
this is (mostly) a backport of #2593 to 3.5. Closes #2593.
2019-01-24 18:44:06 +00:00
9ecf23d3ee Fix some bugs in doxygen config 2019-01-24 11:26:48 +00:00
187f36fe38 ExperienceOrb: clean up some confusing code 2019-01-23 16:46:18 +00:00
dc89b48354 Human: Fixed XP drop amount to match vanilla
In vanilla it doesn't drop the exact number of points you collected. Rather, you lose a little for every level above 1 you had (1 level requires 7 points, later levels require +2 per level), and can recover at most 100 points. Hence, if you had 10 levels, you get back enough points to fill 5 levels and most of a 6th. 14-15 levels gets you the upper bound of about 7.5 levels.
2019-01-23 12:39:25 +00:00
e6d1c1dfbc Living: Get rid of delayed XP spawning, closes #2644
This is not identical to vanilla, but I don't care because it gets rid of edge cases and also makes it easier to integrate with EntityDeathEvent in the future.
2019-01-23 12:31:05 +00:00
5a8812b1dc 3.5.8 is next 2019-01-22 22:14:19 +00:00
4b8e4123af Release 3.5.7 2019-01-22 22:13:35 +00:00
45a4252c26 RCON: Explicitly specify connection backlog size, fixes #2685
I believe this is caused by a bug in the linux kernel, since it only impacts certain machines I tested (one, to be specific). Whatever the case, setting a max backlog size is prudent anyway, and fixes the problem.
2019-01-22 22:11:32 +00:00
feaaa925a7 Fixed a series of denial-of-service bugs in RCON
Packets with a too-short payload would either cause the RCON thread to hang until the client disconnected, or crash the RCON thread entirely.

commit 90bb1894d7f87645b806f5fc67d1b877bb963180
Author: Dylan K. Taylor <odigiman@gmail.com>
Date:   Tue Jan 22 18:15:46 2019 +0000

    fix some bugs in RCON
2019-01-22 22:05:15 +00:00
5221db1178 Updated BinaryUtils dependency 2019-01-22 17:22:11 +00:00
47321114eb login: allow 60 seconds clock drift on login JWT
can everyone please just use NTP already?
2019-01-20 15:51:29 +00:00
a27c9409f1 ExperienceOrb: fixed wrong condition 2019-01-20 12:30:24 +00:00
854f851525 ExperienceOrb: don't follow players in other worlds 2019-01-20 12:30:09 +00:00
9003b38be3 Fixed a wtf in Player->removeWindow() 2019-01-19 19:14:21 +00:00
a6a93f822f 3.5.7 is next 2019-01-19 17:48:16 +00:00
d4851a8f1f Release 3.5.6 2019-01-19 17:33:07 +00:00
480a513f30 Sign: fixed asserts on loading NBT, closes #2636 2019-01-19 16:42:22 +00:00
4fd3bee360 Entity: Address fireticks crashdumps
This will now throw an exception at the source instead of crashing when the entity is saved, which should put the blame on the correct plugin responsible for this.
This also includes magic method hacks to preserve backwards compatibility, since the fireTicks field is now protected.
2019-01-19 16:05:10 +00:00
41fd7545e3 RegionLoader: Account for unexpected EOF when reading chunks, closes #2676 2019-01-19 15:49:19 +00:00
82dddde159 Remove dead code in /time command handler 2019-01-19 15:15:04 +00:00
bc709efb77 Prevent stupidity with /enchant 2019-01-19 15:14:51 +00:00
cd98e6a23e Updated PreProcessor submodule 2019-01-19 13:57:17 +00:00
cb591a98f4 NetworkBinaryStream: Skip item NBT which is too large when encoded
Encoded tags larger than 32KB overflow the length field, so we can't send these over network. However, it's unreasonable to randomly throw this burden off onto users by crashing their servers, so the next best solution is to just not send the NBT. This is also not an ideal solution (books and the like with too-large tags won't work on the client side) but it's better than crashing the server or client due to a protocol bug. Mojang have confirmed this will be resolved by a future MCPE release, so we'll just work around this problem until then.
2019-01-16 21:50:43 +00:00
e9d1af0aee Fixed stack trace encoding bug in CrashDump
it was encoding the real (full) trace, instead of emitting the printable version.
2019-01-16 18:56:56 +00:00
0f545c410a Bow: Improve consistency with vanilla (JE at least), closes #2660
This change causes the existing test I did to now report ~55-60 blocks, which is much closer to parity with vanilla.
2019-01-15 14:42:41 +00:00
1c2ed0836f Sync composer dependencies 2019-01-15 10:26:33 +00:00
6cf30dc813 build 7.3 on travis 2019-01-11 23:54:44 +00:00
f7d9247d39 Server: Permit NULL value entries in pocketmine.yml worlds
this permits listing worlds to load as keys without values.
2019-01-10 19:30:37 +00:00
3380aa3ac2 Config: Assert only whitespace precedes .properties key, fixes #commented properties not being skipped 2019-01-07 12:25:05 +00:00
6a9cad8fb7 3.5.6 is next 2019-01-06 20:18:32 +00:00
c9e598cdb9 Release 3.5.5 2019-01-06 19:55:21 +00:00
a6e5b6e158 Log a debug message when not sending crash due to folder plugin 2019-01-06 19:52:20 +00:00
22a6b817d7 Distinguish between direct and indirect plugin crash involvement
If a plugin was involved in a crash, we can't safely blame it for the crash, since it might have innocently triggered a core bug. Furthermore, it's difficult to accurately detect plugin causing things like invalid argument crashes.
2019-01-06 18:07:29 +00:00
2cdf97b7b5 CrashDump: Scan full stack trace to determine plugin involvement 2019-01-06 18:07:29 +00:00
836cb67850 Server: don't abuse random_bytes() to generate integers 2019-01-06 17:22:31 +00:00
ab37df4484 Server: micro-optimization: avoid unnecessary array_shift()
it's much less expensive to just calculate the modulo of the current tick and 20, and overwrite past entries. The effect is the same. The only difference is that the arrays won't be ordered by time, but that doesn't matter anyway.
2019-01-06 01:08:56 +00:00
93969197f7 Enable status,gc,dumpmemory OOB
dumpmemory has been confined to console by default due to the hazards it poses to a running server.

closes #2528
2019-01-05 18:56:57 +00:00
946a1036f1 Drop warn-if-enabled for asserts
I don't know why this is optional when no other debug warnings are.
2019-01-05 18:49:15 +00:00
43410cdafb Server: warn on assertions !== -1, closes #2640 2019-01-05 18:47:29 +00:00
a99e15012c Backport no-ai hack to disable pre-spawn movement 2019-01-05 17:39:20 +00:00
b22a2ef914 Living: Despawn in endDeathAnimation()
this removes the necessity for the player to do this.
2019-01-05 12:46:11 +00:00
f7f7be896e Server: drop misleading config values 2019-01-05 11:12:09 +00:00
254281cd5e Ice: don't create water for creative players, fixes #2622 2019-01-05 09:26:35 +00:00
5dfceeea98 Fix typo in command.op.take permission description 2019-01-04 23:56:29 +00:00
4b9a142a5d Import global functions and constants for enhanced performance
This is better for performance because these then don't need to be reevaluated every time they are called.

When encountering an unqualified function or constant reference, PHP will first try to locate a symbol in the current namespace by that name, and then fall back to the global namespace.
This short-circuits the check, which has substantial performance effects in some cases - in particular, ord(), chr() and strlen() show ~1500x faster calls when they are fully qualified.

However, this doesn't mean that PM is getting a massive amount faster. In real world terms, this translates to about 10-15% performance improvement.
But before anyone gets excited, you should know that the CodeOptimizer in the PreProcessor repo has been applying fully-qualified symbol optimizations to Jenkins builds for years, which is one of the reasons why Jenkins builds have better performance than home-built or source installations.
We're choosing to do this for the sake of future SafePHP integration and also to be able to get rid of the buggy CodeOptimizer, so that phar and source are more consistent.
2019-01-04 20:43:15 +00:00
0bacf51729 Fix another swathe of number_format() truncation bugs 2019-01-04 19:39:51 +00:00
33f6b441d8 Fixed /gc truncating memory freed
wtf PHP?
2019-01-04 17:30:35 +00:00
11b59498d9 TakeItemEntityPacket: add missing decode, close #2633 2019-01-04 11:45:37 +00:00
d71a543d10 Fixed a bunch of things PHPStan finds unpalatable
close #2614, fix a bunch of docs bugs, fix sendCreativeContents() crash on Human holders, move some inline variable declarations
2019-01-04 00:23:09 +00:00
5e0c3333cf Player: catch more specific exceptions for transactions 2019-01-03 17:57:37 +00:00
0f941410f6 Use more appropriate exceptions in the protocol layer 2019-01-03 17:57:06 +00:00
504cc3bf8b AddEntityPacket: fix some bugs in legacy ID conversion handling 2019-01-03 17:00:16 +00:00
6bd1491b8b AsyncPool: Apply a cooldown to workers to cut down unnecessary GC lag spikes
Since 3.2 there have been some runtime performance issues related to garbage collection and dynamic AsyncWorker booting. This is partly because of GC being dumb about shutting down what it thinks are "unused" workers. A worker which has been idle for a single tick is considered the same as a worker which has been idle for hours. The result of this is that on active servers, workers would get shut down and then immediately restarted because of something like chunk sending. Since booting an async worker is frightfully expensive, this causes lag spikes, which is obviously bad.

This commit changes the GC mechanism to only shutdown workers which have not been used for the last 5 minutes.
2019-01-03 15:06:53 +00:00
658786f2f6 TitleCommand: fix off-by-one bug in "times" subcommand 2019-01-02 21:04:25 +00:00
d34f3f1af3 Add a terminal message for the crash strangler 2019-01-02 19:10:05 +00:00
8650c187f9 Entity: fixed mob head yaw 2019-01-02 15:04:56 +00:00
4b4820cf53 3.5.5 is next 2019-01-01 13:55:45 +00:00
d33acc4fd0 Release 3.5.4 2019-01-01 12:33:17 +00:00
f7de6eb59f Network: Deprecate some garbage
Deprecations on a patch version breaks release protocol, but I don't care at this point. Nobody should have been using this shit anyway.
2018-12-31 22:52:39 +00:00
75a0627bf2 Network: cut this catch-all bullshit out as well
If a network interface crashes, it should take out the whole server, not try to keep on ticking.
2018-12-31 22:40:13 +00:00
8752e363c9 EXCUSE ME, HOW DARE YOU NOT LOG NETWORK ERRORS?! 2018-12-31 22:33:56 +00:00
9ed1b5ca7f Event: More detailed errors for non-cancellable events 2018-12-31 21:29:22 +00:00
1cbb31f1db Player: Reintroduce permission checks for command hints
This was removed way back in 2016 because of an unidentified bug which caused permissible commands not to show up on the client. Back then, command parsing and validity checks were client-sided, and the client would simply not send the command at all if it didn't recognize it. Now, that problem is gone, so it doesn't matter as much if there are permission bugs which cause commands to be erroneously missing.
closes #2625
2018-12-31 19:35:59 +00:00
1393b4c4e2 Player: aDd a HacK foR CliEnt SidE rIghT cLicK SpaM BuG
this bug has existed for so long I forgot it was still here. People stopped pestering me to do something about it, and as a result I forgot to do anything about it.

This hack isn't perfect, but it filters out the worst of the noise. It has side effects for legitimate fast double-clicks, but I don't think anyone will be too bothered - just click more slowly.

This hack may also have negative side effects on poor connections where latency spikes are a problem, but there isn't really much that can be done about that.
2018-12-31 19:16:13 +00:00
2921c86b3c Torch: fixed crash on blockupdate with corrupted meta 2018-12-30 19:50:35 +00:00
9c3a929b65 3.5.4 is next 2018-12-30 19:04:47 +00:00
9abaa42cd7 Release 3.5.3 2018-12-30 18:44:16 +00:00
77b9feb3c0 Player: don't waste CPU time ordering chunks for non-moving players 2018-12-30 18:40:36 +00:00
e0e2e1775f Player: Fixed sluggish chunk updates when not moving
Always order chunks ASAP on chunk change, not just during the spawn sequence. This fixes the sluggishness observed in BlockSniper when doing async chunk modifications.
2018-12-30 17:32:38 +00:00
d2d65ce6cc Attribute: Fix exception messages, make them less useless 2018-12-30 13:44:30 +00:00
ff2e982f22 Updated BinaryUtils dependency 2018-12-30 12:44:08 +00:00
daf56e990b Get rid of some network-layer asserts
NEVER assert on user data. 🤦
2018-12-30 12:42:52 +00:00
3f5e83a322 Backport 23954c4cda to 3.5 branch 2018-12-29 16:39:56 +00:00
5ecc5ed7e0 Get rid of catch-all on chunk unload
god only knows what the fuck is going on in here that warrants this catch-all... so let's remove it and find out!
2018-12-29 16:37:59 +00:00
cd80ae00d4 Handle errors properly on chunk load
Only CorruptedChunkException and UnsupportedChunkFormatException are expected. Anything else should crash the server.
2018-12-29 16:37:10 +00:00
beb5d72299 RegionLoader: fix off-by-one bug with large chunks, closes #2615 2018-12-29 00:02:54 +00:00
0eef634aab Player: Give me ALLLLL your crashdumps
I suspect this is going to cause a firestorm, but once it does we'll be able to see what needs fixing.
2018-12-28 19:30:05 +00:00
0ea166a551 Prevent placement of unknown blocks, closes #2260
I don't know why I ever allowed this in the first place... stupid idea...
2018-12-28 13:03:34 +00:00
6417cff618 Fixed resource packs with comments in manifest
MOJANG, THERE'S NO SUCH THING AS COMMENTS IN STANDARD JSON
2018-12-27 15:50:51 +00:00
a71af952ba Sign: simplify network data reading, ensure text is always 4 lines, closes #2610 2018-12-26 22:57:42 +00:00
93dd05a03e Fixed ender chest sounds, closes #2611 2018-12-26 22:33:51 +00:00
98f903783c Chest: remove pairx and pairz on blockpick, fixes #2612 2018-12-26 22:26:17 +00:00
5d47ea4337 Merge branch 'release/3.4' into release/3.5 2018-12-23 14:04:13 +00:00
c242d6213a Rewrite documentation for PlayerPreLogin, PlayerLogin and PlayerJoin events
this is some of the most awful documentation I've ever seen. No documentation would have been better.
2018-12-23 14:03:19 +00:00
4ad1093fd7 3.5.3 is next 2018-12-22 17:36:29 +00:00
fc0782df02 Release 3.5.2 2018-12-22 17:29:31 +00:00
bfaa224f6b Merge branch 'release/3.4' into release/3.5 2018-12-22 17:29:11 +00:00
de88f0fce1 3.4.4 is next 2018-12-22 17:28:47 +00:00
9b078854c4 Release 3.4.3 2018-12-22 17:17:24 +00:00
42f8e061a5 Merge branch 'release/3.4' into release/3.5 2018-12-22 13:29:41 +00:00
1455c38dbe Utils: fixed crash in getCoreCount(), closes #2600
this should just default to 2 instead of shitting its pants.
2018-12-22 13:27:11 +00:00
75df6973df LevelDB: Account for 2D maps tag being missing
I don't know why this would be missing, but in some cases it is, as seen in the crash archive. Whatever the case, we shouldn't be shitting the bed because of this.
2018-12-22 13:13:14 +00:00
4763360e9e Update BinaryUtils dependency 2018-12-22 13:07:45 +00:00
0299191e64 Attribute: fit value when resetting to default, closes #2599 2018-12-22 11:44:36 +00:00
2664a1b4d8 Merge branch 'release/3.4' into release/3.5 2018-12-21 18:39:42 +00:00
4249c00c3e Level: Fixed generation/send race condition causing blocks to be missing on the client
this FINALLY fixes the remaining occurrences of half-trees.
2018-12-21 18:39:33 +00:00
517c4e5143 Merge branch 'release/3.4' into release/3.5 2018-12-21 17:26:32 +00:00
69c343bb9b Level: fix setChunk() deleting tiles when replacing a chunk with the same chunk
this can be desirable to trigger events related to chunks changing, such as chunk sending.
2018-12-21 17:24:08 +00:00
70df1579a8 Merge branch 'release/3.4' into release/3.5 2018-12-20 20:02:00 +00:00
ea9f9aa250 Update some non-critical protocol magic numbers 2018-12-20 19:59:42 +00:00
34a899e28b Clean up Utils error handling functions (internal) 2018-12-16 17:50:00 +00:00
b80868040e Utils: fixed getTrace() including itself in trace when no alt trace is given
it always seemed a little strange that crashdump trace would pop 4 frames when only 3 are written in the comment...
2018-12-16 17:15:16 +00:00
a7f1181335 Merge branch 'release/3.4' into release/3.5 2018-12-16 14:13:19 +00:00
bf8a8b386e Allow ~relative coordinates to work in /particle 2018-12-16 14:12:46 +00:00
4b518f2a58 Merge branch 'release/3.4' into release/3.5 2018-12-14 17:32:34 +00:00
60b1f0a6e9 Fixed burning TNT setting affected mobs on fire when exploding, closes #2561 2018-12-14 17:32:11 +00:00
5934399a0d 3.5.2 is next 2018-12-14 09:46:12 +00:00
b42132a7c3 Release 3.5.1 2018-12-14 09:45:47 +00:00
c05697f506 Merge branch 'release/3.4' into release/3.5 2018-12-14 09:39:21 +00:00
d4fe1b8ece 3.4.3 is next 2018-12-14 09:30:44 +00:00
9b2653fb6f Release 3.4.2 2018-12-14 09:30:14 +00:00
ed88684e71 Fixed invisible FloatingTextParticle crashing the server, closes #2560 2018-12-14 09:30:14 +00:00
cbb9c4f298 Entity: require scale > 0 in setScale(), fixes #2563 2018-12-14 09:30:14 +00:00
660d42e8d1 Backport usage of SetLocalPlayerAsInitializedPacket to 3.4 (#2558)
This fixes various problems, such as forms not working on PlayerJoinEvent.
2018-12-13 20:07:17 +00:00
dbeceb02f9 fixup 1.8 crafting, take 2 2018-12-13 10:54:15 +00:00
fd77dd0066 Revert "Fixed crafting grid transaction handling, close #2559"
This reverts commit dfeb62491a.
2018-12-13 10:38:04 +00:00
87ce87112b Merge branch 'release/3.4' into release/3.5 2018-12-13 09:56:21 +00:00
1d71f5edb3 DataPacket: more detail in error messages for undefined fields 2018-12-13 09:55:50 +00:00
0f620157e8 3.5.1 is next 2018-12-12 19:20:40 +00:00
2323601f98 Release 3.5.0 2018-12-12 19:03:07 +00:00
d34b94302f fixed lava fizz sound 2018-12-12 18:00:43 +00:00
ec4c61e113 fix extradata defaults for broadcastLevelSoundEvent
fixes TNT sounds not working, amongst other things
2018-12-12 17:42:52 +00:00
231e491bb9 Fixed black spawn eggs 2018-12-12 17:14:13 +00:00
69cdc6f13a Remove misleading default value for NetworkInventoryAction windowId 2018-12-12 16:08:47 +00:00
dfeb62491a Fixed crafting grid transaction handling, close #2559 2018-12-12 15:41:54 +00:00
178eedb536 Merge branch 'release/3.4' into release/3.5 2018-12-12 10:12:12 +00:00
4975da2aae NetworkInventoryAction: additional validity checks 2018-12-12 10:11:44 +00:00
5946ec8819 fix inventory bug, silence debug spam, shut the fuck up MCPE 2018-12-11 21:57:07 +00:00
abf0dee426 bump version 2018-12-11 21:07:56 +00:00
30f5a8fac6 Protocol changes for 1.8.0 release 2018-12-11 21:05:03 +00:00
f704061618 Tree: fixed being able to overwrite other trees
this was observable by planting a sapling underneath an existing tree and punching it with bone meal.

This change will also prevent trees generating too close together.
2018-12-09 19:26:48 +00:00
23dc6e09d8 Sync DevTools submodule 2018-12-09 15:34:06 +00:00
15b7fc978e 3.4.2 is next 2018-12-08 17:00:36 +00:00
bb396174ba Release 3.4.1 2018-12-08 17:00:07 +00:00
dcef3cba21 CrashDump: cleanup some version related stuff
this should have been done a long time ago, but we didn't want to cause compatibility problems with CA. Now it enforces version checks, this isn't a problem anymore.
2018-12-08 16:58:06 +00:00
5f8a9f8747 Add a new format_version field to crashdumps
this will be used in the future to allow CA to decide how to decode crashdumps and/or refuse crashdumps from incompatible versions.
2018-12-08 16:57:57 +00:00
84e41e6967 3.4.1 is next 2018-12-06 21:01:57 +00:00
5e0e0daf7d Release 3.4.0 2018-12-06 20:45:57 +00:00
a95694ed06 Add signature validation for some user-defined callbacks 2018-12-04 18:33:58 +00:00
762405d16a Add daverandom/callback-validator as a dependency 2018-12-04 17:14:37 +00:00
e3f46987f5 Liquid: Add events to allow controlling flow and fusion (#2547) 2018-12-04 13:14:22 +00:00
e4223bb7dc Level: Duct tape fix for crashy trees at the top of the world
this doesn't fix shit but it at least doesn't crash. Fixing this properly can't be effectively done any other way without backwards compatibility breaks. Fortunately it's not common practice to grow trees at the top of the world.
2018-12-03 18:30:27 +00:00
f091446ec7 Sync NBT dependency 2018-12-03 16:15:02 +00:00
b0f891081c Mark EXHAUSTION as non-syncable
this attribute is not visible on the client and is only used for controlling saturation depletion. It's extremely spammy and as such really shouldn't be sent over network. This has also been causing some minor client-side performance issues in survival.
2018-12-02 16:43:00 +00:00
acd7c9b336 Permission: Throw exception on unknown values in getByName()
Previously, writing wrong values into plugin.yml for permission defaults would cause the permission to be silently denied to everyone.
2018-12-01 15:56:44 +00:00
75482124f2 Merge branch 'release/3.3' into release/3.4 2018-12-01 10:09:46 +00:00
288599cbe7 3.3.5 is next 2018-12-01 10:00:59 +00:00
aa7206126a Release 3.3.4 2018-12-01 10:00:38 +00:00
1a6db1c7ce DataPacket: add missing field
this must have been missing for how many years now? thanks @shoghicp

this is why we don't do releases on friday night... in my defence my device had the beta installed...
2018-12-01 09:29:53 +00:00
f1c071ce7f Release 3.3.3 2018-11-30 19:41:36 +00:00
e2f46a4358 Remove unused import... 2018-11-30 19:40:35 +00:00
36c0c350a7 Merge branch 'release/3.3' into release/3.4 2018-11-30 18:37:28 +00:00
4c08a05fae Barf on trying to read/write nonexisting fields of packets
this should make it easier to debug problems when content of packets changes during protocol updates.
2018-11-30 18:36:28 +00:00
6295ef8a81 Add language option to server.properties (#2531)
This allows to save the language without rewriting pocketmine.yml. Since this is a "standard" config option (something that the user might want to directly modify) it's reasonable to put it in server.properties. pocketmine.yml is generally reserved for more advanced configuration options.
2018-11-30 13:25:04 +00:00
05dba61a69 Merge branch 'release/3.3' into release/3.4 2018-11-29 19:47:28 +00:00
b473ffdedc Remove async playerdata saving, closes #2515
this technically involves non-breaking API changes which should happen on a patch release, but I can't be bothered with the dust cleanup, so we'll just blow it away now. It doesn't hurt anyone anyway.
2018-11-29 19:47:15 +00:00
60dddcd12a Painting: clean up guard checks, remove unnecessary checks 2018-11-29 19:29:10 +00:00
c010ef45ed Merge branch 'release/3.3' into release/3.4 2018-11-29 18:46:00 +00:00
93c26a0b0c Living: Suspend effects ticking on death
This was the cause of a bug with regeneration which caused players taking fatal damage under regeneration not to die correctly. On the server side they would die and immediately regenerate some health, which would cause the next attribute sync to not report the health drop to zero, which made the client unaware that it was dead.

Perhaps attributes should be forcibly synced in some circumstances, but nonetheless regeneration shouldn't apply post-death.
2018-11-29 18:45:46 +00:00
08ec021f78 Merge branch 'release/3.3' into release/3.4 2018-11-26 14:02:32 +00:00
545ec9c881 Updated PreProcessor submodule 2018-11-26 14:02:23 +00:00
b0060caaf7 Config: don't catch-all in save() 2018-11-25 16:35:59 +00:00
c90d1faa81 Merge remote-tracking branch 'origin/release/3.3' into release/3.4 2018-11-25 14:35:45 +00:00
d5a1961e6b Force minimum uptime to be >= 120 seconds if a crash occurs (#2534)
This is an incremental improvement over 4a6841a5a4. This change works better because it also reduces disk spam of crashdumps.

This will now sleep if the server uptime was less than 120 seconds before crashing. If unattended, this will clamp down on automated crashdump spam. If attended, the user can simply press CTRL+C to abort the process and skip the delay.
2018-11-25 14:35:35 +00:00
449dda83fb Merge branch 'release/3.3' into release/3.4 2018-11-22 16:48:57 +00:00
6bc79149c3 SubChunk: Fixed $changed not getting set in setBlock() when only block data changed
it was comparing a string and an int. This now compares the integer values first.
2018-11-22 16:47:25 +00:00
cdf7e28251 shut up PhpStorm 2018-11-17 18:12:48 +00:00
a02f422d85 SubChunk: Fixed constant redefinition on worker threads when autoloading
this happens when workers inherit constants but not classes.
2018-11-17 16:29:53 +00:00
f8bfbc107d Reduce chunk memory usage by 20-60% by exploiting PHP copy-on-write behaviour (#2527)
This takes advantage of two key behaviours of PHP:
1. Assigning a string does not copy the string
2. Changing an offset in a string causes the string to be copied.

These two factors combined, along with the fact that blocklight and skylight arrays are usually all-zeros, allow us to produce a significant memory usage reduction of loaded chunks.
A freshly generated PM world with 3,332 chunks loaded drops from 310MB to 200MB memory usage with these changes applied.
2018-11-17 14:46:05 +00:00
554c029fbd Merge branch 'release/3.3' into release/3.4 2018-11-13 18:24:08 +00:00
e018311e73 Make start script errors a bit more noob-friendly 2018-11-13 18:23:54 +00:00
de50f02076 Merge branch 'release/3.3' into release/3.4 2018-11-12 22:07:22 +00:00
71d02e5870 Improve dev build error messages 2018-11-12 22:07:14 +00:00
46d9475568 Use Utils::getNiceClosureName() in PluginManager 2018-11-11 19:50:07 +00:00
788b278fc3 Utils: fixed handling of non-anonymous closure functions 2018-11-11 19:43:00 +00:00
2e4143f57e Merge branch 'release/3.3' into release/3.4 2018-11-11 12:38:53 +00:00
d312aef1ac 3.3.3 is next 2018-11-11 11:58:51 +00:00
200de3fe84 Release 3.3.2 2018-11-11 11:58:25 +00:00
f560a6efea Merge tag '3.2.7' into release/3.3 2018-11-11 11:24:23 +00:00
7ecd7fd13f Release 3.2.7 2018-11-11 11:23:20 +00:00
5284ad0346 Merge branch 'release/3.3' into release/3.4 2018-11-11 11:15:46 +00:00
b893645a81 Merge branch 'release/3.2' into release/3.3 2018-11-11 11:15:39 +00:00
b19b3134ad PluginManager: reduce unnecessary indentation 2018-11-11 11:15:27 +00:00
7cf36f460b Merge branch 'release/3.3' into release/3.4 2018-11-10 22:37:08 +00:00
243f86b0a0 Merge branch 'release/3.2' into release/3.3 2018-11-10 22:37:02 +00:00
9156cbc269 PluginManager: Make registerEvents() check order more logical
Prioritize validating that the function is actually a handler, before trying to parse its doc comment.
2018-11-10 22:36:46 +00:00
a5f776af2f Merge branch 'release/3.3' into release/3.4 2018-11-07 22:11:13 +00:00
43fe6a1934 Merge branch 'release/3.2' into release/3.3 2018-11-07 20:02:28 +00:00
342a74ffcb Level: Collect garbage from chunk internals in doChunkGarbageCollection() 2018-11-07 20:01:07 +00:00
3d2701e775 Merge branch 'release/3.3' into release/3.4 2018-11-04 23:32:56 +00:00
2183bf875c Merge remote-tracking branch 'origin/release/3.2' into release/3.3 2018-11-04 23:32:33 +00:00
8cc2a4ce5d Remove start script support for source-code installations (#2495)
This was suggested recently by @TheDeibo. We don't want users running source-code installations unless they are developers, and developers should know how to boot a source-code installation anyway.
2018-11-04 23:31:57 +00:00
e26af3fa1b TaskScheduler: don't catch unexpected exceptions
this means that errors in scheduled tasks which are uncaught will now cause a server crash.
2018-11-04 23:22:30 +00:00
1634dd62e3 Don't catch unexpected exceptions during command execution 2018-11-04 23:11:51 +00:00
755db3dac8 Added a ClosureTask implementation for easier task scheduling (#2497) 2018-11-04 22:55:40 +00:00
3dabf90b0e Merge branch 'release/3.3' into release/3.4 2018-11-04 22:38:58 +00:00
f61e14e341 Merge branch 'release/3.2' into release/3.3 2018-11-04 22:38:45 +00:00
7b24fbc8db Utils: fix a mistake in getNiceClassName() doc 2018-11-04 22:38:38 +00:00
0543c17849 Merge branch 'release/3.3' into release/3.4 2018-11-04 22:15:46 +00:00
c4f3426bae Merge branch 'release/3.2' into release/3.3 2018-11-04 22:15:21 +00:00
046c39b02e Remove some Throwable abuse in AsyncTasks 2018-11-04 22:15:06 +00:00
87b471ce0f AsyncPool: reverse e0d5c79848, don't catch unexpected exceptions thrown by onCompletion()
this should never throw an uncaught exception, and if it does it indicates broken code.
2018-11-04 22:09:30 +00:00
055ba6aa7c Merge branch 'release/3.3' into release/3.4 2018-11-04 11:57:35 +00:00
5c3eed40b3 Merge branch 'release/3.2' into release/3.3 2018-11-04 11:57:28 +00:00
3e5237b6e0 ItemEntity: remove useless instanceof 2018-11-04 11:57:22 +00:00
af1227f154 Merge branch 'release/3.3' into release/3.4 2018-11-03 19:43:54 +00:00
d9a867016c Merge branch 'release/3.2' into release/3.3 2018-11-03 19:43:45 +00:00
a50a863ab7 Chunk: be more intelligent about fast-serializing chunks
This reduces the amount of useless data that pthreads has to copy around.
2018-11-03 19:43:35 +00:00
9caf62778c AsyncTask: remove $serialize parameter from setResult()
Whether serialization is necessary can be determined automatically based on the type of variable.
2018-11-03 16:56:24 +00:00
d257d36e55 Merge branch 'release/3.3' into release/3.4 2018-11-03 15:14:27 +00:00
1b03168b88 Merge branch 'release/3.2' into release/3.3 2018-11-03 15:12:40 +00:00
6b9fee05d6 Fixed performance bug with chunk sending
this process of fast-serialization, fast-deserialize, network-serialize is an order of magnitude slower than just doing the network encode directly on the main thread, and also copies more useless data.

For the main thread, the figures were something like 3x more expensive, and then an extra 7x for deserialization on the worker thread. This is a ridiculously large overhead.
2018-11-03 15:12:30 +00:00
44d8a5528e Merge branch 'release/3.3' into release/3.4 2018-11-03 12:12:42 +00:00
45a18ffe1e Merge branch 'release/3.2' into release/3.3 2018-11-03 12:12:23 +00:00
f0182c9996 TaskHandler: remove incorrect internal warning
this is perfectly fine to use, and preferable to getting a cyclic ref to the scheduler. TaskScheduler->cancelTask() does pretty much the exact same thing, and the scheduler internals are designed to deal with this anyway.
2018-11-03 12:12:02 +00:00
265b61b3e6 Merge branch 'release/3.3' into release/3.4 2018-10-31 18:55:26 +00:00
2d88058710 Merge branch 'release/3.2' into release/3.3 2018-10-31 18:55:18 +00:00
ab48d85c35 Properly deal with anonymous tasks in timings 2018-10-31 18:51:30 +00:00
cf43f479df Server: cleanup setting up of console 2018-10-30 16:59:03 +00:00
c143834632 Merge branch 'release/3.3' into release/3.4 2018-10-30 15:43:06 +00:00
d9b7a28747 Merge branch 'release/3.2' into release/3.3 2018-10-30 15:42:52 +00:00
31ceafa111 Chest: keep inventory better in sync when paired
should fix #2502
2018-10-30 15:42:44 +00:00
a0eb6e23e5 Merge branch 'release/3.3' into release/3.4 2018-10-29 12:42:17 +00:00
694d7d4e20 Merge branch 'release/3.2' into release/3.3 2018-10-29 12:42:10 +00:00
2da2fdd6d4 Added a test for Item->equals() when both items have no NBT 2018-10-29 12:42:03 +00:00
0aa30295af Merge branch 'release/3.3' into release/3.4 2018-10-26 20:09:02 +01:00
c1c56f29bb Merge branch 'release/3.2' into release/3.3 2018-10-26 20:08:55 +01:00
9b820a0849 Guard against possible overflow bug in NetworkBinaryStream 2018-10-26 20:08:48 +01:00
c6a4bc4bf7 Merge branch 'release/3.3' into release/3.4 2018-10-25 19:36:44 +01:00
3128449033 3.3.2 is next 2018-10-25 19:36:20 +01:00
a60154e0b7 Release 3.3.1 2018-10-25 19:29:57 +01:00
4cbbf2e91c Merge branch 'release/3.2' into release/3.3 2018-10-25 19:29:34 +01:00
b0624aff9f 3.2.7 is next 2018-10-25 19:28:54 +01:00
c38e2c5ccb Release 3.2.6 2018-10-25 19:20:26 +01:00
02ef0bfbb4 Remove unnecessary quotes
these appear on the echoed message, which is undesirable.
2018-10-25 18:49:06 +01:00
a714612453 Merge branch 'release/3.3' into release/3.4 2018-10-25 18:42:09 +01:00
4835537886 Merge branch 'release/3.2' into release/3.3 2018-10-25 18:41:58 +01:00
4a6841a5a4 Added client side self rate-limiting for crashdump reporting
this should produce some reduction in spam at the source.

This could also be used to control the rate at which constantly-crashing servers restart to stop them spamming the disk as well, but the main concern here is eliminating crash archive involuntary DDoS by crashy servers.
2018-10-25 18:10:59 +01:00
f61e099828 Merge branch 'release/3.3' into release/3.4 2018-10-24 15:52:04 +01:00
925da62afa Merge branch 'release/3.2' into release/3.3 2018-10-24 15:49:09 +01:00
09985c5763 Fixed async light population producing garbage when generator isn't registered, closes #2488 2018-10-24 15:49:00 +01:00
447b9562bb Merge branch 'release/3.3' into release/3.4 2018-10-24 12:16:46 +01:00
d1ee9eb960 Merge branch 'release/3.2' into release/3.3 2018-10-24 12:00:55 +01:00
196cf8a68d Fixed missing MoveEntityDeltaPacket field 2018-10-24 12:00:25 +01:00
cac21c2caf SubChunk: implement branchless read/write for nibble arrays (#2489)
this was inspired by https://hub.spigotmc.org/stash/projects/SPIGOT/repos/spigot/browse/CraftBukkit-Patches/0121-Branchless-NibbleArray.patch
2018-10-22 17:46:14 +01:00
6dd2597934 Merge branch 'release/3.3' into release/3.4 2018-10-21 18:17:07 +01:00
5e68858ebf Merge branch 'release/3.2' into release/3.3 2018-10-21 18:16:59 +01:00
45c9caa38c Fixup some formatting issues 2018-10-21 18:15:25 +01:00
b35759cc25 Add /unban and /unban-ip as aliases of /pardon and /pardon-ip 2018-10-21 15:32:38 +01:00
2a40c0d82c Make use of isInLoadedTerrain() 2018-10-20 19:13:34 +01:00
8ac1b18b17 Level: add API method isInLoadedTerrain() 2018-10-20 19:09:53 +01:00
4aef9919dc Use newly added API method 2018-10-20 16:26:10 +01:00
43426a4c5c Level: Add API method getViewersForPosition()
This returns all players who have the given position within their view radius.
2018-10-20 16:25:56 +01:00
3028832cd3 Entity: remove redundant check from spawnTo()
this won't be reached if the player isn't using this chunk anyway.
2018-10-20 16:24:46 +01:00
9f8a2dc61a Make use of new API method getChunkAtPosition() 2018-10-20 15:58:29 +01:00
d9ebe6f321 Level: Added API method getChunkAtPosition()
This returns the chunk containing the given vector.
2018-10-20 15:54:13 +01:00
cb1eb1ee09 Level: Rename addGlobalPacket() to broadcastGlobalPacket()
this name makes the intention more clear and consistent with other functions.
2018-10-20 15:24:33 +01:00
d563b9e31b Level: Added API method broadcastPacketToViewers()
This supersedes addChunkPacket() in most cases, and has a more clear name. It broadcasts the given packet to every player who has the target position within their chunk load radius.
2018-10-20 15:14:41 +01:00
7c44eea625 Merge branch 'release/3.3' into release/3.4 2018-10-19 18:53:18 +01:00
d749f19c73 Merge branch 'release/3.2' into release/3.3 2018-10-19 18:53:12 +01:00
41fd03f329 LightUpdate: fixed double-updated nodes not getting light propagated appropriately
This can happen when a light source is removed and later encountering another light source to fill the gap. A higher light level may get set and then not propagated. This bug is difficult to explain, but fairly easy to reproduce.
2018-10-19 18:53:04 +01:00
646c8970b8 Merge branch 'release/3.3' into release/3.4 2018-10-19 15:56:01 +01:00
58067b2ad1 Merge branch 'release/3.2' into release/3.3 2018-10-19 15:55:53 +01:00
0c9946621c Level: Do not tick chunks which have unloaded adjacent chunks
Grass can cause issues here by requesting blocks randomly offset away from itself, which can cause silent chunk loading on chunk ticking. It also causes crashes if chunk autoloading is taken away, which is obviously undesired.

It was also noticed that player chunkloaders cause chunks to start getting ticked as soon as they load their first chunk, which is before the entity is visible to everyone else on the server. This is probably undesired behaviour.
2018-10-19 15:48:46 +01:00
f1cd6940f9 Merge branch 'release/3.3' into release/3.4 2018-10-16 22:56:46 +01:00
af5637e050 PlayerListEntry: remove dead fields 2018-10-16 22:56:21 +01:00
4221e274d6 Merge branch 'release/3.3' into release/3.4 2018-10-16 18:20:14 +01:00
a524b0e447 3.3.1 is next 2018-10-16 18:19:49 +01:00
88a5e92c20 Release 3.3.0 2018-10-16 17:47:35 +01:00
b876ae4ef8 Merge branch 'release/3.2' into release/3.3 2018-10-16 17:26:46 +01:00
1983964f9e 3.2.6 is next 2018-10-16 17:26:04 +01:00
c4c55a45c9 Release 3.2.5 2018-10-16 17:17:53 +01:00
c5cd813b76 bump PM version 2018-10-16 17:15:49 +01:00
bc2dff3f51 version numbers 2018-10-16 17:15:26 +01:00
839d5eab7b Protocol changes for 1.7
there's also some new cases in stats, but we don't care about those anyway.
2018-10-16 17:13:52 +01:00
cd506bb443 shuffle back to 3.4 to make space for new MCPE release 2018-10-16 17:11:46 +01:00
4c8ffce86f Merge branch 'release/3.2' into release/3.3 2018-10-16 16:46:39 +01:00
78923177f9 VersionString: use appropriate regex for number matching 2018-10-16 16:46:27 +01:00
df6bb2ea0e Merge branch 'release/3.2' into release/3.3 2018-10-16 09:51:19 +01:00
b7062e7bff CrashDump: don't try to report code that doesn't exist
this can happen when eval() is used, and then we get a big blank mess with nothing on it. eval() is a special case that should be handled separately, but for now this is just fixing a bug.
2018-10-16 09:50:59 +01:00
ba68192206 Fixed bad event handlers (whose errors get caught) breaking recursion protection for future event calls
This was observed in a recent crashdump where a plugin triggered a recursion error, but the stack trace did not contain any sign of a recursive event call. I conclude that this must have been caused by previous event handlers triggering errors 50 times in order to make the recursion detection break, because the recursion detection did not decrement the counter in cases where an exception was thrown.
2018-10-14 11:07:16 +01:00
6579930638 Revamp MetadataStore API (#2477)
This would be a lot less messy if we had generics, but no tango.
2018-10-12 12:16:21 +01:00
a0ab996b9f Merge branch 'release/3.2' into release/3.3 2018-10-12 09:31:48 +01:00
97980d4516 Update composer dependency versions 2018-10-12 09:31:19 +01:00
b261129788 Merge branch 'release/3.2' into release/3.3 2018-10-11 19:42:18 +01:00
d9220395d1 Dummy decode for ResourcePacksInfoPacket and ResourcePackStackPacket
while we can't deal with this information, it's needed for the sake of unit testing so we don't shit on every bit of incoming data of these packet types.
2018-10-11 19:42:00 +01:00
4f2f373a24 Merge branch 'release/3.2' into release/3.3 2018-10-10 13:41:51 +01:00
2858db430e Fixed AsyncTask publishProgress() race condition on task exit
It's possible for a progress update to be lost due to the task finishing before the main thread found the progress update.
2018-10-10 13:41:15 +01:00
de6d62aba2 Merge branch 'release/3.2' into release/3.3 2018-10-09 22:51:40 +01:00
32836cbfb8 Don't handle remaining packets in a batch when an earlier one triggered a disconnect 2018-10-09 22:50:02 +01:00
8316e00927 Player: Throw exception on failure to encode form JSON 2018-10-09 22:39:48 +01:00
6f694b0801 Merge branch 'release/3.2' into release/3.3 2018-10-07 19:45:26 +01:00
fd459cda54 3.2.5 is next 2018-10-07 19:45:06 +01:00
a66dd4a7d9 Release 3.2.4 2018-10-07 19:32:04 +01:00
3617eba4a3 Merge branch 'release/3.1' into release/3.2 2018-10-07 19:31:16 +01:00
e79cc98883 Release 3.1.8 2018-10-07 19:20:20 +01:00
a3552875cb Merge branch 'release/3.2' into release/3.3 2018-10-07 17:48:26 +01:00
d259b2c9ee Merge branch 'release/3.1' into release/3.2 2018-10-07 17:48:19 +01:00
10fa74b417 Make clear that Plugin->setEnabled() is @internal
Use of this by plugins will produce a lot of undefined behaviour, such as event handlers not being unregistered, scheduled tasks not being removed, and registered permissions causing memory leaks.
2018-10-07 17:48:11 +01:00
ab5aec6c30 Event: Remove unnecessary check from call() hot path
This check is completely unnecessary since handlers get unregistered when a plugin is disabled. Additionally, this is an extremely hot path and this change produces a modest 5% performance improvement to event calls.
2018-10-07 16:36:30 +01:00
0e508876d2 RakLibInterface: Disconnect players who trigger errors during handler
this is cleaner than leaving the player hanging for 5 seconds (which they'll often timeout from anyway). Banning the IP without kicking the player can often look like "lag" and end up getting brushed off as a performance issue.
2018-10-07 15:32:23 +01:00
50b89c30f8 Merge branch 'release/3.2' into release/3.3 2018-10-06 14:45:12 +01:00
17ceb27af4 Merge branch 'release/3.1' into release/3.2 2018-10-06 14:45:05 +01:00
adbd1c7bed RCON: remove redundant sleep
this dates back to the days where PM used to kill threads to stop them. Today we're more civilized and ask it to stop nicely, so this isn't necessary anymore.
2018-10-06 14:44:56 +01:00
495fdbd19f Move block and network namespaces away from PluginManager->callEvent()
the original step that wasn't supposed to cause conflicts, caused messy conflicts... so I might as well do this part too
2018-10-05 18:22:49 +01:00
620784e4e7 Merge branch 'release/3.2' into release/3.3 2018-10-05 17:44:03 +01:00
cf20e626e2 Merge branch 'release/3.1' into release/3.2 2018-10-05 17:43:54 +01:00
d75c830a7e Add -f parameter to lint.sh to allow it to not be useless in cygwin
find can conflict with windows' built in find command, which causes it to bug out when running tests.
2018-10-05 17:43:45 +01:00
1dd6591ac1 Migrate a bunch of PluginManager->callEvent() usages to Event->call
This has the triple bonus effect of a) making a lot of code easier to read, b) reducing Server::getInstance() usages, and c) removing a whole bunch of Server dependencies.

The network and block namespaces are untouched by this commit due to potential for merge conflicts. These should be dealt with separately on master.
2018-10-05 17:30:06 +01:00
6efef3bbc7 Move event calling functionality to Event->call() method
This is dependent on the changes made in b1e0f82cbf. This now makes it possible to call events without fetching a Server reference, allowing to eliminate a vast array of Server dependencies.
2018-10-05 16:55:37 +01:00
b1e0f82cbf PluginManager: Stop catching exceptions thrown by event handlers (#2472)
The basic principle here is "if you're not expecting it, don't catch it".

Event handlers are **never** supposed to throw exceptions. If they do throw exceptions, it's usually going to one of two things;
1. Broken code producing an error
2. Code triggering (and not catching) a runtime error

Both 1) and 2) boil down to defective code on the part of the event handler, and thus should not be caught by the caller, but instead allowed to crash the server and produce a crashdump.

It's also undesirable to catch unexpected errors here for a few other reasons
- It leaves the owner of the event handler in an unknown, potentially unstable state
- It allows broken code to cause event handlers to spam the logger in events that happen frequently (for example movement handlers)
- It allows the process to continue down a train of further undefined behaviour, which may lead to more errors or ultimately a crash, so it makes no sense to hold off the inevitable.

This has a few advantages that are not merely inverted disadvantages:
- Crash dumps will now be created and automatically submitted for defective event handlers, allowing quicker issue location, debugging and fixing in plugins without manual user interaction
- Event calling now isn't dependent on Server to work.
2018-10-05 16:46:10 +01:00
c065cfbeda Merge branch 'release/3.2' into release/3.3 2018-10-04 16:41:03 +01:00
722924a779 Merge branch 'release/3.1' into release/3.2 2018-10-04 16:40:55 +01:00
60e1b29462 RegionLoader: Remove incorrect size cap
This assumes that the region is properly garbage-collected and packed, but if the file contains uncollected garbage this may not be the case, resulting in a region larger than a gigabyte.
2018-10-04 16:40:45 +01:00
0171095036 Merge branch 'release/3.2' into release/3.3 2018-09-29 15:39:34 +01:00
5b511f6d06 Merge branch 'release/3.1' into release/3.2 2018-09-29 15:39:27 +01:00
426dee04a6 Potion: remove unnecessary exception throw in getPotionEffectsById()
this is only used by Potion and SplashPotion, and simply causes errors when trying to use potions with unknown IDs.
2018-09-29 15:39:20 +01:00
9d8898a4ed Server: added API method hasOfflinePlayerData() 2018-09-27 16:36:42 +01:00
3bb22f9778 Merge branch 'release/3.2' into release/3.3 2018-09-26 13:12:34 +01:00
bb1944ca40 Merge branch 'release/3.1' into release/3.2 2018-09-26 13:12:20 +01:00
d1a20ecb4a CommandReader: Require readline to be explicitly enabled on Windows
readline on Windows causes issues with console output corruption. Additionally, PM readline impl is extremely buggy and probably ought to be removed. However, have a hotfix for now.
2018-09-26 13:11:21 +01:00
16c636df83 Merge branch 'release/3.2' into release/3.3 2018-09-24 18:27:04 -04:00
f6a8ec83a1 Merge branch 'release/3.1' into release/3.2 2018-09-24 18:26:39 -04:00
28137efb53 Fixed server freezing when using chorus fruit from large Y coordinates 2018-09-24 18:26:20 -04:00
e597067a92 Merge branch 'release/3.3' of https://github.com/pmmp/pocketmine-mp into release/3.3 2018-09-23 16:43:36 +01:00
06f00020cd Merge branch 'release/3.2' into release/3.3 2018-09-23 16:35:20 +01:00
7b0836d399 Merge branch 'release/3.1' into release/3.2 2018-09-23 16:35:11 +01:00
cea146e335 Thin: use bounding box instead of collision boxes 2018-09-23 16:35:01 +01:00
5eeaeb6c3e Level: Bail on trying to unload a level during level tick (#2435) 2018-09-22 13:40:50 +01:00
2712287995 Merge branch 'release/3.2' into release/3.3 2018-09-20 19:02:39 +01:00
8db1ccc1ae Merge branch 'release/3.1' into release/3.2 2018-09-20 19:02:09 +01:00
5d56030afa Item: make nbtDeserialize() return AIR when reading an unknown PC item
This is scummy, but it's better than crashing the whole server just because a chest contained an unknown item.
2018-09-20 19:00:44 +01:00
6be5e75263 Merge branch 'release/3.2' into release/3.3 2018-09-20 17:04:55 +01:00
d9c251b613 Merge branch 'release/3.1' into release/3.2 2018-09-20 17:04:45 +01:00
8085b81f5c fix phars 2018-09-20 17:04:34 +01:00
6b44f99dfb Merge branch 'release/3.2' into release/3.3 2018-09-20 16:50:04 +01:00
33d3fff3c5 Merge branch 'release/3.1' into release/3.2 2018-09-20 16:49:57 +01:00
7c092b93b4 Fixed bug when placing blocks by clicking on redstone ore 2018-09-20 16:49:50 +01:00
aa05650994 Fixed block picking for mob heads 2018-09-20 13:11:45 +01:00
758d9b9784 Farmland: fixed block picking 2018-09-20 12:03:01 +01:00
24a6bf7365 PocketMine.php: Allow overriding autoloader path using --bootstrap
I've gotten tired of re-running composer every time I switch branches...
2018-09-20 12:01:39 +01:00
9a5d51fd3d Fixed block-picking cake giving the block instead of item 2018-09-20 11:31:48 +01:00
fa9ea6a7d7 Merge branch 'release/3.2' into release/3.3 2018-09-20 10:04:19 +01:00
6a7f39978b Merge branch 'release/3.1' into release/3.2 2018-09-20 10:03:47 +01:00
c52e1ea9f9 Fixed block picking double slabs giving the double slab block 2018-09-20 10:02:55 +01:00
5e94d20d79 Merge branch 'release/3.2' into release/3.3 2018-09-19 16:17:00 +01:00
a0bb747d6d Merge branch 'release/3.1' into release/3.2 2018-09-19 16:16:18 +01:00
4bc0d850b1 Added Block->getRuntimeId(), clean up some mess 2018-09-19 16:16:10 +01:00
ad9df6764d Merge branch 'release/3.2' into release/3.3 2018-09-18 12:32:07 +01:00
97583c8b04 Merge branch 'release/3.1' into release/3.2 2018-09-18 12:32:01 +01:00
107192c753 Bed: fixed block-pick giving wrong colour items 2018-09-18 12:31:53 +01:00
6309a242dc Merge branch 'release/3.2' into release/3.3 2018-09-18 12:22:26 +01:00
870f9abc20 Merge branch 'release/3.1' into release/3.2 2018-09-18 12:22:20 +01:00
0e2bbc44db Fixed drops and item picking of Brewing Stand 2018-09-18 12:22:12 +01:00
e58d015f14 Merge branch 'release/3.2' into release/3.3 2018-09-16 17:47:08 +01:00
d9768abe47 Merge branch 'release/3.1' into release/3.2 2018-09-16 17:47:01 +01:00
e9b84ecc8b Fixed incorrect break check for torch 2018-09-16 17:46:50 +01:00
0d65f9c4b8 Merge branch 'release/3.2' into release/3.3 2018-09-14 17:09:51 +01:00
c83d12790e Merge branch 'release/3.1' into release/3.2 2018-09-14 17:09:41 +01:00
5863d4c066 Fixed PermissibleBase->clearPermissions() not unsubscribing from permissions that aren't explicitly assigned
This came to light after observing cfb6856634 in a fresh light. I noticed that this fix should not have been necessary because clearPermissions() should have dealt with it. Unfortunately, permissions can be set without being set in PermissibleBase->permissions, so this misses things.
2018-09-14 17:06:32 +01:00
22077c1fdd Merge branch 'release/3.2' into release/3.3 2018-09-14 16:18:19 +01:00
7d54d18732 Merge branch 'release/3.1' into release/3.2 2018-09-14 16:18:12 +01:00
bfbc845efa Remove impossible uses of PlayerInteractEvent CLICK_AIR constants 2018-09-14 16:17:55 +01:00
f33c19e77a Merge branch 'release/3.2' into release/3.3 2018-09-14 11:06:24 +01:00
2ff4228fb7 Merge branch 'release/3.1' into release/3.2 2018-09-14 11:06:11 +01:00
06c4f31db7 Server: Account for later levels being unloaded by earlier levels' ticking function in checkTickUpdates()
should fix #2434

This happens when a plugin causes a level to be unloaded during an event fired on level tick.
2018-09-14 11:05:51 +01:00
09dea035d4 Level: Batch light updates at the end of the tick to amortize CPU cost (#2429)
this produces a 5x performance improvement for lighting updates during water flow, and 25% improvement for lava flow.
2018-09-12 10:33:28 +01:00
a9fc67663c Strip anti flight out of the core (#2428)
This may later be developed into a plugin if it is a desired feature, but having it in the core is unnecessary and a pain in the ass.
2018-09-12 10:06:57 +01:00
519659fd2b Merge branch 'release/3.2' into release/3.3 2018-09-11 19:48:23 +01:00
6c70e84fa2 Merge branch 'release/3.1' into release/3.2 2018-09-11 19:47:46 +01:00
7d0e631a75 RakLibInterface: fixed processing hook being registered too early
this would cause bugs if the interface was not added directly to the network.
2018-09-11 19:47:26 +01:00
5134c0cf5a Merge branch 'release/3.2' into release/3.3 2018-09-11 12:28:09 +01:00
65b751d080 3.2.4 is next 2018-09-11 12:27:45 +01:00
27effff403 Release 3.2.3 2018-09-11 12:19:56 +01:00
a940cc5b5e Merge branch 'release/3.1' into release/3.2 2018-09-11 12:19:32 +01:00
15e654131c 3.1.8 is next 2018-09-11 12:18:54 +01:00
6e6cda91ce Release 3.1.7 2018-09-11 11:45:17 +01:00
0aa63d269a Merge branch 'release/3.2' into release/3.3 2018-09-11 11:35:46 +01:00
53a76c0d14 Merge branch 'release/3.1' into release/3.2 2018-09-11 11:35:38 +01:00
69500fe183 LightUpdate: Remove garbage left over from dab73d8950 2018-09-11 11:35:31 +01:00
191f0038b8 LightUpdate: Allow a single position to be set more than once before executing
This is needed for batched lighting updates to work. It also reduces the overhead involved with simply preparing a lighting update and moves the pain to the execute() instead.
2018-09-11 11:33:57 +01:00
99d6aa92cb Implemented rail connectivity (#2414) 2018-09-10 19:32:11 +01:00
90d01f5ed2 Merge branch 'release/3.2' into release/3.3 2018-09-08 14:25:20 +01:00
5af4dd20df Merge branch 'release/3.1' into release/3.2 2018-09-08 14:25:11 +01:00
c7d58db7eb Cleanup Entity age handling, fixed arrows despawning too quickly after long flight 2018-09-08 14:23:06 +01:00
a3b78236eb Server: don't catch Throwable for level ticking
this usually causes the console to get spammed with errors. Additionally, in the case where doTick() throws any exception, it's usually because we're in a state we didn't want to be in, so we really should not carry on trying to keep ticking when something breaks here. Instead, this should generate a crashdump.
2018-09-08 14:13:28 +01:00
b70905b287 Merge branch 'release/3.2' into release/3.3 2018-09-06 19:31:05 +01:00
d8e27e6081 Bow: fix wrong arithmetic for Flame fire ticks, closes #2420 2018-09-06 19:30:55 +01:00
7a48c0b23d Merge branch 'release/3.2' into release/3.3 2018-09-06 19:15:41 +01:00
14a2ffa51b Merge branch 'release/3.1' into release/3.2 2018-09-06 18:43:28 +01:00
c447d51e3f Bucket: use ItemFactory instead of self-clone
in the future Item->setDamage() will be removed.
2018-09-06 18:42:09 +01:00
557fd34754 Make MainLogger independent of runtime-defined INI entries
Previously every thread using the logger had to inherit runtime-defined INI entries in order for the timezone to be set correctly. This removes that requirement.
2018-09-04 15:57:45 +01:00
32077d96b4 Merge branch 'release/3.2' into release/3.3 2018-09-04 11:56:58 +01:00
9f4722f537 3.2.3 is next 2018-09-04 11:56:27 +01:00
cb04f287eb Release 3.2.2 2018-09-04 11:51:28 +01:00
f649ef5195 Sync 3.2 and 3.1 branches 2018-09-04 11:51:05 +01:00
b615cad22d 3.1.7 is next 2018-09-04 11:50:05 +01:00
b93e219231 Release 3.1.6 2018-09-04 11:44:05 +01:00
a4a9309193 Updated NBT dependency for bug fix 2018-09-04 11:43:38 +01:00
e621cde8f1 Player: Tighten validity checks for addWindow() (#2419)
- Don't allow the same window ID to be used when another window is already using it
- Detect window ID collisions when selecting IDs for regular containers (should never happen, but anything is possible)
2018-09-01 15:25:46 +01:00
56ee957fda 3.2.2 is next 2018-08-31 19:03:58 +01:00
2738e38aee Merge branch 'release/3.2' into release/3.3 2018-08-31 16:19:52 +01:00
72d447276b Merge branch 'release/3.2' into release/3.3 2018-08-30 15:46:54 +01:00
d0aff2ecbd Bump version for 3.3 dev branch 2018-08-30 11:05:58 +01:00
371 changed files with 5835 additions and 2131 deletions

View File

@ -4,3 +4,7 @@ root = yes
[*]
indent_size = 4
indent_style = tab
[*.yml]
indent_size = 2
indent_style = space

View File

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

View File

@ -27,9 +27,11 @@
"pocketmine/raklib": "^0.12.0",
"pocketmine/spl": "^0.3.0",
"pocketmine/binaryutils": "^0.1.0",
"pocketmine/nbt": "^0.2.0",
"pocketmine/nbt": "^0.2.6",
"pocketmine/math": "^0.2.0",
"pocketmine/snooze": "^0.1.0"
"pocketmine/snooze": "^0.1.0",
"daverandom/callback-validator": "dev-master",
"adhocore/json-comment": "^0.0.7"
},
"autoload": {
"psr-4": {

166
composer.lock generated
View File

@ -4,20 +4,104 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "2670b9e2a730ff758909be8b9e9d609a",
"content-hash": "2f5313e4ebd7b62c785cf683b27464b4",
"packages": [
{
"name": "pocketmine/binaryutils",
"version": "0.1.1",
"name": "adhocore/json-comment",
"version": "v0.0.7",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BinaryUtils.git",
"reference": "54efeb978be0ff9335022729fe63c1e2077bf1be"
"url": "https://github.com/adhocore/php-json-comment.git",
"reference": "135356c7e7336ef59924f1d921c770045f937a76"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/54efeb978be0ff9335022729fe63c1e2077bf1be",
"reference": "54efeb978be0ff9335022729fe63c1e2077bf1be",
"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",
"source": {
"type": "git",
"url": "https://github.com/DaveRandom/CallbackValidator.git",
"reference": "d87a08cddbc6099816ed01e50ce25cdfc43b542f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/DaveRandom/CallbackValidator/zipball/d87a08cddbc6099816ed01e50ce25cdfc43b542f",
"reference": "d87a08cddbc6099816ed01e50ce25cdfc43b542f",
"shasum": ""
},
"require": {
"ext-reflection": "*",
"php": ">=7.0"
},
"require-dev": {
"phpunit/phpunit": "^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"DaveRandom\\CallbackValidator\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Chris Wright",
"email": "cw@daverandom.com"
}
],
"description": "Tools for validating callback signatures",
"time": "2017-04-03T15:22:41+00:00"
},
{
"name": "pocketmine/binaryutils",
"version": "0.1.8",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BinaryUtils.git",
"reference": "33f511715d22418c03368b49b45a6c25d6b33806"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/33f511715d22418c03368b49b45a6c25d6b33806",
"reference": "33f511715d22418c03368b49b45a6c25d6b33806",
"shasum": ""
},
"require": {
@ -35,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": {
@ -69,26 +153,27 @@
],
"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.0",
"version": "0.2.6",
"source": {
"type": "git",
"url": "https://github.com/pmmp/NBT.git",
"reference": "da19487ff92f6f7a16b5ce8894132bb1d1e9ea0c"
"reference": "92eaf84dd61f700d3ec02ebd01b606cb5b1590d4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/da19487ff92f6f7a16b5ce8894132bb1d1e9ea0c",
"reference": "da19487ff92f6f7a16b5ce8894132bb1d1e9ea0c",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/92eaf84dd61f700d3ec02ebd01b606cb5b1590d4",
"reference": "92eaf84dd61f700d3ec02ebd01b606cb5b1590d4",
"shasum": ""
},
"require": {
"ext-zlib": "*",
"php": ">=7.2.0",
"php-64bit": "*",
"pocketmine/binaryutils": "^0.1.0"
@ -109,23 +194,23 @@
],
"description": "PHP library for working with Named Binary Tags",
"support": {
"source": "https://github.com/pmmp/NBT/tree/0.2.0",
"source": "https://github.com/pmmp/NBT/tree/0.2.6",
"issues": "https://github.com/pmmp/NBT/issues"
},
"time": "2018-06-13T09:56:00+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": {
@ -150,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": {
@ -184,23 +269,23 @@
],
"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",
"version": "0.3.1",
"version": "0.3.2",
"source": {
"type": "git",
"url": "https://github.com/pmmp/SPL.git",
"reference": "ca3912099543ddc4b4b14f40e258d84ca547dfa5"
"reference": "7fd53857cd000491ba69e8db865792a024dd2c49"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/SPL/zipball/ca3912099543ddc4b4b14f40e258d84ca547dfa5",
"reference": "ca3912099543ddc4b4b14f40e258d84ca547dfa5",
"url": "https://api.github.com/repos/pmmp/SPL/zipball/7fd53857cd000491ba69e8db865792a024dd2c49",
"reference": "7fd53857cd000491ba69e8db865792a024dd2c49",
"shasum": ""
},
"type": "library",
@ -217,16 +302,17 @@
],
"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-06-09T17:30:36+00:00"
"time": "2018-08-12T15:17:39+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"ext-pthreads": 20
"ext-pthreads": 20,
"daverandom/callback-validator": 20
},
"prefer-stable": false,
"prefer-lowest": false,

View File

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

View File

@ -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,54 +257,74 @@ 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();
$this->addLine("Code:");
$this->data["code"] = [];
if($this->server->getProperty("auto-report.send-code", true) !== false){
if($this->server->getProperty("auto-report.send-code", true) !== false and file_exists($error["fullFile"])){
$file = @file($error["fullFile"], FILE_IGNORE_NEW_LINES);
for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10; ++$l){
$this->addLine("[" . ($l + 1) . "] " . @$file[$l]);
$this->data["code"][$l + 1] = @$file[$l];
for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10 and isset($file[$l]); ++$l){
$this->addLine("[" . ($l + 1) . "] " . $file[$l]);
$this->data["code"][$l + 1] = $file[$l];
}
}
$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");

View File

@ -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{
@ -185,7 +218,7 @@ class MemoryManager{
}
$ev = new LowMemoryEvent($memory, $limit, $global, $triggerCount);
$this->server->getPluginManager()->callEvent($ev);
$ev->call();
$cycles = 0;
if($this->garbageCollectionTrigger){
@ -473,7 +506,7 @@ class MemoryManager{
self::continueDump($value, $data[$key], $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
}
}elseif(is_string($from)){
$data = "(string) len(". strlen($from) .") " . substr(Utils::printable($from), 0, $maxStringSize);
$data = "(string) len(" . strlen($from) . ") " . substr(Utils::printable($from), 0, $maxStringSize);
}elseif(is_resource($from)){
$data = "(resource) " . print_r($from, true);
}else{

View File

@ -35,7 +35,7 @@ class OfflinePlayer implements IPlayer, Metadatable{
/** @var Server */
private $server;
/** @var CompoundTag|null */
private $namedtag;
private $namedtag = null;
/**
* @param Server $server
@ -44,10 +44,8 @@ class OfflinePlayer implements IPlayer, Metadatable{
public function __construct(Server $server, string $name){
$this->server = $server;
$this->name = $name;
if(file_exists($this->server->getDataPath() . "players/" . strtolower($this->name) . ".dat")){
if($this->server->hasOfflinePlayerData($this->name)){
$this->namedtag = $this->server->getOfflinePlayerData($this->name);
}else{
$this->namedtag = null;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,7 @@ namespace pocketmine {
use pocketmine\wizard\SetupWizard;
const NAME = "PocketMine-MP";
const BASE_VERSION = "3.2.1";
const BASE_VERSION = "3.6.2";
const IS_DEVELOPMENT_BUILD = false;
const BUILD_NUMBER = 0;
@ -145,12 +145,18 @@ namespace pocketmine {
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
}
define('pocketmine\COMPOSER_AUTOLOADER_PATH', \pocketmine\PATH . 'vendor/autoload.php');
$opts = getopt("", ["bootstrap:"]);
if(isset($opts["bootstrap"])){
$bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"];
}else{
$bootstrap = \pocketmine\PATH . 'vendor/autoload.php';
}
define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap);
if(is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
if(\pocketmine\COMPOSER_AUTOLOADER_PATH !== false and is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
}else{
critical_error("Composer autoloader not found.");
critical_error("Composer autoloader not found at " . $bootstrap);
critical_error("Please install/update Composer dependencies or use provided builds.");
exit(1);
}
@ -171,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);
@ -239,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);

View File

@ -91,7 +91,6 @@ use pocketmine\plugin\PluginManager;
use pocketmine\plugin\ScriptPluginLoader;
use pocketmine\resourcepacks\ResourcePackManager;
use pocketmine\scheduler\AsyncPool;
use pocketmine\scheduler\FileWriteTask;
use pocketmine\scheduler\SendUsageTask;
use pocketmine\snooze\SleeperHandler;
use pocketmine\snooze\SleeperNotifier;
@ -99,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;
@ -107,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
@ -198,9 +266,6 @@ class Server{
/** @var ResourcePackManager */
private $resourceManager;
/** @var ConsoleCommandSender */
private $consoleSender;
/** @var int */
private $maxPlayers;
@ -556,10 +621,11 @@ class Server{
}
/**
* @deprecated
* @return bool
*/
public function getAllowFlight() : bool{
return $this->getConfigBool("allow-flight", false);
return true;
}
/**
@ -734,6 +800,17 @@ class Server{
return $result;
}
/**
* Returns whether the server has stored any saved data for this player.
*
* @param string $name
*
* @return bool
*/
public function hasOfflinePlayerData(string $name) : bool{
return file_exists($this->getDataPath() . "players/$name.dat");
}
/**
* @param string $name
*
@ -805,22 +882,17 @@ class Server{
/**
* @param string $name
* @param CompoundTag $nbtTag
* @param bool $async
*/
public function saveOfflinePlayerData(string $name, CompoundTag $nbtTag, bool $async = false){
public function saveOfflinePlayerData(string $name, CompoundTag $nbtTag){
$ev = new PlayerDataSaveEvent($nbtTag, $name);
$ev->setCancelled(!$this->shouldSavePlayerData());
$this->pluginManager->callEvent($ev);
$ev->call();
if(!$ev->isCancelled()){
$nbt = new BigEndianNBTStream();
try{
if($async){
$this->asyncPool->submitTask(new FileWriteTask($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed($ev->getSaveData())));
}else{
file_put_contents($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed($ev->getSaveData()));
}
file_put_contents($this->getDataPath() . "players/" . strtolower($name) . ".dat", $nbt->writeCompressed($ev->getSaveData()));
}catch(\Throwable $e){
$this->logger->critical($this->getLanguage()->translateString("pocketmine.data.saveError", [$name, $e->getMessage()]));
$this->logger->logException($e);
@ -991,6 +1063,7 @@ class Server{
/**
* @internal
*
* @param Level $level
*/
public function removeLevel(Level $level) : void{
@ -1033,7 +1106,7 @@ class Server{
$this->levels[$level->getId()] = $level;
$this->getPluginManager()->callEvent(new LevelLoadEvent($level));
(new LevelLoadEvent($level))->call();
$level->setTickRate($this->baseTickRate);
@ -1055,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", "");
@ -1082,9 +1155,9 @@ class Server{
$level->setTickRate($this->baseTickRate);
$this->getPluginManager()->callEvent(new LevelInitEvent($level));
(new LevelInitEvent($level))->call();
$this->getPluginManager()->callEvent(new LevelLoadEvent($level));
(new LevelLoadEvent($level))->call();
$this->getLogger()->notice($this->getLanguage()->translateString("pocketmine.level.backgroundGeneration", [$name]));
@ -1437,31 +1510,6 @@ class Server{
}
$this->config = new Config($this->dataPath . "pocketmine.yml", Config::YAML, []);
define('pocketmine\DEBUG', (int) $this->getProperty("debug.level", 1));
$this->forceLanguage = (bool) $this->getProperty("settings.force-language", false);
$this->baseLang = new BaseLang($this->getProperty("settings.language", BaseLang::FALLBACK_LANGUAGE));
$this->logger->info($this->getLanguage()->translateString("language.selected", [$this->getLanguage()->getName(), $this->getLanguage()->getLang()]));
if(\pocketmine\IS_DEVELOPMENT_BUILD and !((bool) $this->getProperty("settings.enable-dev-builds", false))){
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error1", [\pocketmine\NAME]));
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error2"));
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error3"));
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error4", ["settings.enable-dev-builds"]));
$this->forceShutdown();
return;
}
if(((int) ini_get('zend.assertions')) > 0 and ((bool) $this->getProperty("debug.assertions.warn-if-enabled", true)) !== false){
$this->logger->warning("Debugging assertions are enabled, this may impact on performance. To disable them, set `zend.assertions = -1` in php.ini.");
}
ini_set('assert.exception', '1');
if($this->logger instanceof MainLogger){
$this->logger->setLogDebug(\pocketmine\DEBUG > 1);
}
$this->logger->info("Loading server properties...");
$this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, [
"motd" => \pocketmine\NAME . " Server",
@ -1470,9 +1518,6 @@ class Server{
"announce-player-achievements" => true,
"spawn-protection" => 16,
"max-players" => 20,
"allow-flight" => false,
"spawn-animals" => true,
"spawn-mobs" => true,
"gamemode" => 0,
"force-gamemode" => false,
"hardcore" => false,
@ -1487,9 +1532,36 @@ class Server{
"rcon.password" => substr(base64_encode(random_bytes(20)), 3, 10),
"auto-save" => true,
"view-distance" => 8,
"xbox-auth" => true
"xbox-auth" => true,
"language" => "eng"
]);
define('pocketmine\DEBUG', (int) $this->getProperty("debug.level", 1));
$this->forceLanguage = (bool) $this->getProperty("settings.force-language", false);
$this->baseLang = new BaseLang($this->getConfigString("language", $this->getProperty("settings.language", BaseLang::FALLBACK_LANGUAGE)));
$this->logger->info($this->getLanguage()->translateString("language.selected", [$this->getLanguage()->getName(), $this->getLanguage()->getLang()]));
if(\pocketmine\IS_DEVELOPMENT_BUILD and !((bool) $this->getProperty("settings.enable-dev-builds", false))){
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error1", [\pocketmine\NAME]));
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error2"));
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error3"));
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error4", ["settings.enable-dev-builds"]));
$this->logger->emergency($this->baseLang->translateString("pocketmine.server.devBuild.error5", ["https://github.com/pmmp/PocketMine-MP/releases"]));
$this->forceShutdown();
return;
}
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.");
}
ini_set('assert.exception', '1');
if($this->logger instanceof MainLogger){
$this->logger->setLogDebug(\pocketmine\DEBUG > 1);
}
$this->memoryManager = new MemoryManager($this);
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.start", [TextFormat::AQUA . $this->getVersion() . TextFormat::RESET]));
@ -1527,10 +1599,22 @@ class Server{
$this->doTitleTick = ((bool) $this->getProperty("console.title-tick", true)) && Terminal::hasFormattingCodes();
$consoleSender = new ConsoleCommandSender();
PermissionManager::getInstance()->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $consoleSender);
$consoleNotifier = new SleeperNotifier();
$this->console = new CommandReader($consoleNotifier);
$this->tickSleeper->addNotifier($consoleNotifier, function() : void{
$this->checkConsole();
$this->tickSleeper->addNotifier($consoleNotifier, function() use ($consoleSender) : void{
Timings::$serverCommandTimer->startTiming();
while(($line = $this->console->getLine()) !== null){
$ev = new ServerCommandEvent($consoleSender, $line);
$ev->call();
if(!$ev->isCancelled()){
$this->dispatchCommand($ev->getSender(), $ev->getCommand());
}
}
Timings::$serverCommandTimer->stopTiming();
});
$this->console->start(PTHREADS_INHERIT_NONE);
@ -1606,7 +1690,6 @@ class Server{
Timings::init();
TimingsHandler::setEnabled((bool) $this->getProperty("settings.enable-profiling", false));
$this->consoleSender = new ConsoleCommandSender();
$this->commandMap = new SimpleCommandMap($this);
Entity::init();
@ -1623,7 +1706,6 @@ class Server{
$this->resourceManager = new ResourcePackManager($this->getDataPath() . "resource_packs" . DIRECTORY_SEPARATOR, $this->logger);
$this->pluginManager = new PluginManager($this, $this->commandMap, ((bool) $this->getProperty("plugins.legacy-data-dir", true)) ? null : $this->getDataPath() . "plugin_data" . DIRECTORY_SEPARATOR);
PermissionManager::getInstance()->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender);
$this->profilingTickRate = (float) $this->getProperty("settings.profile-report-trigger", 20);
$this->pluginManager->registerInterface(new PharPluginLoader($this->autoloader));
$this->pluginManager->registerInterface(new ScriptPluginLoader());
@ -1648,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)){
@ -1922,17 +2006,6 @@ class Server{
$this->pluginManager->disablePlugins();
}
public function checkConsole(){
Timings::$serverCommandTimer->startTiming();
while(($line = $this->console->getLine()) !== null){
$this->pluginManager->callEvent($ev = new ServerCommandEvent($this->consoleSender, $line));
if(!$ev->isCancelled()){
$this->dispatchCommand($ev->getSender(), $ev->getCommand());
}
}
Timings::$serverCommandTimer->stopTiming();
}
/**
* Executes a command from a CommandSender
*
@ -1944,7 +2017,8 @@ class Server{
*/
public function dispatchCommand(CommandSender $sender, string $commandLine, bool $internal = false) : bool{
if(!$internal){
$this->pluginManager->callEvent($ev = new CommandEvent($sender, $commandLine));
$ev = new CommandEvent($sender, $commandLine);
$ev->call();
if($ev->isCancelled()){
return false;
}
@ -2073,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");
@ -2168,7 +2239,7 @@ class Server{
"fullFile" => $e->getFile(),
"file" => $errfile,
"line" => $errline,
"trace" => Utils::getTrace(0, $trace)
"trace" => $trace
];
global $lastExceptionError, $lastError;
@ -2195,11 +2266,19 @@ class Server{
if($this->getProperty("auto-report.enabled", true) !== false){
$report = true;
$stamp = $this->getDataPath() . "crashdumps/.last_crash";
$crashInterval = 120; //2 minutes
if(file_exists($stamp) and !($report = (filemtime($stamp) + $crashInterval < time()))){
$this->logger->debug("Not sending crashdump due to last crash less than $crashInterval seconds ago");
}
@touch($stamp); //update file timestamp
$plugin = $dump->getData()["plugin"];
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");
}
}
@ -2237,6 +2316,13 @@ class Server{
$this->forceShutdown();
$this->isRunning = false;
//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());
exit(1);
}
@ -2309,7 +2395,7 @@ class Server{
$pk = new PlayerListPacket();
$pk->type = PlayerListPacket::TYPE_ADD;
$pk->entries[] = PlayerListEntry::createAdditionEntry($uuid, $entityId, $name, "", 0, $skin, $xboxUserId);
$pk->entries[] = PlayerListEntry::createAdditionEntry($uuid, $entityId, $name, $skin, $xboxUserId);
$this->broadcastPacket($players ?? $this->playerList, $pk);
}
@ -2332,7 +2418,7 @@ class Server{
$pk = new PlayerListPacket();
$pk->type = PlayerListPacket::TYPE_ADD;
foreach($this->playerList as $player){
$pk->entries[] = PlayerListEntry::createAdditionEntry($player->getUniqueId(), $player->getId(), $player->getDisplayName(), "", 0, $player->getSkin(), $player->getXuid());
$pk->entries[] = PlayerListEntry::createAdditionEntry($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkin(), $player->getXuid());
}
$p->dataPacket($pk);
@ -2348,41 +2434,37 @@ class Server{
}
//Do level ticks
foreach($this->getLevels() as $level){
foreach($this->levels as $k => $level){
if(!isset($this->levels[$k])){
// Level unloaded during the tick of a level earlier in this loop, perhaps by plugin
continue;
}
if($level->getTickRate() > $this->baseTickRate and --$level->tickRateCounter > 0){
continue;
}
try{
$levelTime = microtime(true);
$level->doTick($currentTick);
$tickMs = (microtime(true) - $levelTime) * 1000;
$level->tickRateTime = $tickMs;
if($this->autoTickRate){
if($tickMs < 50 and $level->getTickRate() > $this->baseTickRate){
$level->setTickRate($r = $level->getTickRate() - 1);
if($r > $this->baseTickRate){
$level->tickRateCounter = $level->getTickRate();
}
$this->getLogger()->debug("Raising level \"{$level->getName()}\" tick rate to {$level->getTickRate()} ticks");
}elseif($tickMs >= 50){
if($level->getTickRate() === $this->baseTickRate){
$level->setTickRate(max($this->baseTickRate + 1, min($this->autoTickRateLimit, (int) floor($tickMs / 50))));
$this->getLogger()->debug(sprintf("Level \"%s\" took %gms, setting tick rate to %d ticks", $level->getName(), (int) round($tickMs, 2), $level->getTickRate()));
}elseif(($tickMs / $level->getTickRate()) >= 50 and $level->getTickRate() < $this->autoTickRateLimit){
$level->setTickRate($level->getTickRate() + 1);
$this->getLogger()->debug(sprintf("Level \"%s\" took %gms, setting tick rate to %d ticks", $level->getName(), (int) round($tickMs, 2), $level->getTickRate()));
}
$levelTime = microtime(true);
$level->doTick($currentTick);
$tickMs = (microtime(true) - $levelTime) * 1000;
$level->tickRateTime = $tickMs;
if($this->autoTickRate){
if($tickMs < 50 and $level->getTickRate() > $this->baseTickRate){
$level->setTickRate($r = $level->getTickRate() - 1);
if($r > $this->baseTickRate){
$level->tickRateCounter = $level->getTickRate();
}
$this->getLogger()->debug("Raising level \"{$level->getName()}\" tick rate to {$level->getTickRate()} ticks");
}elseif($tickMs >= 50){
if($level->getTickRate() === $this->baseTickRate){
$level->setTickRate(max($this->baseTickRate + 1, min($this->autoTickRateLimit, (int) floor($tickMs / 50))));
$this->getLogger()->debug(sprintf("Level \"%s\" took %gms, setting tick rate to %d ticks", $level->getName(), (int) round($tickMs, 2), $level->getTickRate()));
}elseif(($tickMs / $level->getTickRate()) >= 50 and $level->getTickRate() < $this->autoTickRateLimit){
$level->setTickRate($level->getTickRate() + 1);
$this->getLogger()->debug(sprintf("Level \"%s\" took %gms, setting tick rate to %d ticks", $level->getName(), (int) round($tickMs, 2), $level->getTickRate()));
}
$level->tickRateCounter = $level->getTickRate();
}
}catch(\Throwable $e){
if(!$level->isClosed()){
$this->logger->critical($this->getLanguage()->translateString("pocketmine.level.tickError", [$level->getName(), $e->getMessage()]));
}else{
$this->logger->critical($this->getLanguage()->translateString("pocketmine.level.tickUnloadError", [$level->getName()]));
}
$this->logger->logException($e);
}
}
}
@ -2392,7 +2474,7 @@ class Server{
Timings::$worldSaveTimer->startTiming();
foreach($this->players as $index => $player){
if($player->spawned){
$player->save(true);
$player->save();
}elseif(!$player->isConnected()){
$this->removePlayer($player);
}
@ -2476,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);
}
@ -2529,7 +2609,7 @@ class Server{
}
if(($this->tickCounter & 0b111111111) === 0){
$this->getPluginManager()->callEvent($this->queryRegenerateTask = new QueryRegenerateEvent($this, 5));
($this->queryRegenerateTask = new QueryRegenerateEvent($this, 5))->call();
if($this->queryHandler !== null){
$this->queryHandler->regenerateInfo();
}
@ -2569,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;

View File

@ -28,7 +28,7 @@ namespace pocketmine;
*/
abstract class Thread extends \Thread{
/** @var \ClassLoader */
/** @var \ClassLoader|null */
protected $classLoader;
/** @var string|null */
protected $composerAutoloaderPath;

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine;
use pocketmine\utils\MainLogger;
use function spl_object_hash;
class ThreadManager extends \Volatile{

View File

@ -28,7 +28,7 @@ namespace pocketmine;
*/
abstract class Worker extends \Worker{
/** @var \ClassLoader */
/** @var \ClassLoader|null */
protected $classLoader;
/** @var string|null */
protected $composerAutoloaderPath;

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
class ActivatorRail extends Rail{
class ActivatorRail extends RedstoneRail{
protected $id = self::ACTIVATOR_RAIL;

View File

@ -0,0 +1,273 @@
<?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;
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{
public const STRAIGHT_NORTH_SOUTH = 0;
public const STRAIGHT_EAST_WEST = 1;
public const ASCENDING_EAST = 2;
public const ASCENDING_WEST = 3;
public const ASCENDING_NORTH = 4;
public const ASCENDING_SOUTH = 5;
private const ASCENDING_SIDES = [
self::ASCENDING_NORTH => Vector3::SIDE_NORTH,
self::ASCENDING_EAST => Vector3::SIDE_EAST,
self::ASCENDING_SOUTH => Vector3::SIDE_SOUTH,
self::ASCENDING_WEST => Vector3::SIDE_WEST
];
protected const FLAG_ASCEND = 1 << 24; //used to indicate direction-up
protected const CONNECTIONS = [
//straights
self::STRAIGHT_NORTH_SOUTH => [
Vector3::SIDE_NORTH,
Vector3::SIDE_SOUTH
],
self::STRAIGHT_EAST_WEST => [
Vector3::SIDE_EAST,
Vector3::SIDE_WEST
],
//ascending
self::ASCENDING_EAST => [
Vector3::SIDE_WEST,
Vector3::SIDE_EAST | self::FLAG_ASCEND
],
self::ASCENDING_WEST => [
Vector3::SIDE_EAST,
Vector3::SIDE_WEST | self::FLAG_ASCEND
],
self::ASCENDING_NORTH => [
Vector3::SIDE_SOUTH,
Vector3::SIDE_NORTH | self::FLAG_ASCEND
],
self::ASCENDING_SOUTH => [
Vector3::SIDE_NORTH,
Vector3::SIDE_SOUTH | self::FLAG_ASCEND
]
];
public function __construct(int $meta = 0){
$this->meta = $meta;
}
public function getHardness() : float{
return 0.7;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if(!$blockReplace->getSide(Vector3::SIDE_DOWN)->isTransparent() and $this->getLevel()->setBlock($blockReplace, $this, true, true)){
$this->tryReconnect();
return true;
}
return false;
}
protected static function searchState(array $connections, array $lookup) : int{
$meta = array_search($connections, $lookup, true);
if($meta === false){
$meta = array_search(array_reverse($connections), $lookup, true);
}
if($meta === false){
throw new \InvalidArgumentException("No meta value matches connections " . implode(", ", array_map('\dechex', $connections)));
}
return $meta;
}
/**
* Returns a meta value for the rail with the given connections.
*
* @param array $connections
*
* @return int
*
* @throws \InvalidArgumentException if no state matches the given connections
*/
protected function getMetaForState(array $connections) : int{
return self::searchState($connections, self::CONNECTIONS);
}
/**
* Returns the connection directions of this rail (depending on the current block state)
*
* @return int[]
*/
abstract protected function getConnectionsForState() : array;
/**
* Returns all the directions this rail is already connected in.
*
* @return int[]
*/
private function getConnectedDirections() : array{
/** @var int[] $connections */
$connections = [];
/** @var int $connection */
foreach($this->getConnectionsForState() as $connection){
$other = $this->getSide($connection & ~self::FLAG_ASCEND);
$otherConnection = Vector3::getOppositeSide($connection & ~self::FLAG_ASCEND);
if(($connection & self::FLAG_ASCEND) !== 0){
$other = $other->getSide(Vector3::SIDE_UP);
}elseif(!($other instanceof BaseRail)){ //check for rail sloping up to meet this one
$other = $other->getSide(Vector3::SIDE_DOWN);
$otherConnection |= self::FLAG_ASCEND;
}
if(
$other instanceof BaseRail and
in_array($otherConnection, $other->getConnectionsForState(), true)
){
$connections[] = $connection;
}
}
return $connections;
}
private function getPossibleConnectionDirections(array $constraints) : array{
switch(count($constraints)){
case 0:
//No constraints, can connect in any direction
$possible = [
Vector3::SIDE_NORTH => true,
Vector3::SIDE_SOUTH => true,
Vector3::SIDE_WEST => true,
Vector3::SIDE_EAST => true
];
foreach($possible as $p => $_){
$possible[$p | self::FLAG_ASCEND] = true;
}
return $possible;
case 1:
return $this->getPossibleConnectionDirectionsOneConstraint(array_shift($constraints));
case 2:
return [];
default:
throw new \InvalidArgumentException("Expected at most 2 constraints, got " . count($constraints));
}
}
protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{
$opposite = Vector3::getOppositeSide($constraint & ~self::FLAG_ASCEND);
$possible = [$opposite => true];
if(($constraint & self::FLAG_ASCEND) === 0){
//We can slope the other way if this connection isn't already a slope
$possible[$opposite | self::FLAG_ASCEND] = true;
}
return $possible;
}
private function tryReconnect() : void{
$thisConnections = $this->getConnectedDirections();
$changed = false;
do{
$possible = $this->getPossibleConnectionDirections($thisConnections);
$continue = false;
foreach($possible as $thisSide => $_){
$otherSide = Vector3::getOppositeSide($thisSide & ~self::FLAG_ASCEND);
$other = $this->getSide($thisSide & ~self::FLAG_ASCEND);
if(($thisSide & self::FLAG_ASCEND) !== 0){
$other = $other->getSide(Vector3::SIDE_UP);
}elseif(!($other instanceof BaseRail)){ //check if other rails can slope up to meet this one
$other = $other->getSide(Vector3::SIDE_DOWN);
$otherSide |= self::FLAG_ASCEND;
}
if(!($other instanceof BaseRail) or count($otherConnections = $other->getConnectedDirections()) >= 2){
//we can only connect to a rail that has less than 2 connections
continue;
}
$otherPossible = $other->getPossibleConnectionDirections($otherConnections);
if(isset($otherPossible[$otherSide])){
$otherConnections[] = $otherSide;
$other->updateState($otherConnections);
$changed = true;
$thisConnections[] = $thisSide;
$continue = count($thisConnections) < 2;
break; //force recomputing possible directions, since this connection could invalidate others
}
}
}while($continue);
if($changed){
$this->updateState($thisConnections);
}
}
private function updateState(array $connections) : void{
if(count($connections) === 1){
$connections[] = Vector3::getOppositeSide($connections[0] & ~self::FLAG_ASCEND);
}elseif(count($connections) !== 2){
throw new \InvalidArgumentException("Expected exactly 2 connections, got " . count($connections));
}
$this->meta = $this->getMetaForState($connections);
$this->level->setBlock($this, $this, false, false); //avoid recursion
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() or (
isset(self::ASCENDING_SIDES[$this->meta & 0x07]) and
$this->getSide(self::ASCENDING_SIDES[$this->meta & 0x07])->isTransparent()
)){
$this->getLevel()->useBreakOn($this);
}
}
public function getVariantBitmask() : int{
return 0;
}
}

View File

@ -192,21 +192,25 @@ class Bed extends Transparent{
public function getDropsForCompatibleTool(Item $item) : array{
if($this->isHeadPart()){
$tile = $this->getLevel()->getTile($this);
if($tile instanceof TileBed){
return [
ItemFactory::get($this->getItemId(), $tile->getColor())
];
}else{
return [
ItemFactory::get($this->getItemId(), 14) //Red
];
}
return [$this->getItem()];
}
return [];
}
public function getPickedItem() : Item{
return $this->getItem();
}
private function getItem() : Item{
$tile = $this->getLevel()->getTile($this);
if($tile instanceof TileBed){
return ItemFactory::get($this->getItemId(), $tile->getColor());
}
return ItemFactory::get($this->getItemId(), 14); //Red
}
public function isAffectedBySilkTouch() : bool{
return false;
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use function mt_rand;
class Beetroot extends Crops{

View File

@ -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{
@ -109,6 +112,14 @@ class Block extends Position implements BlockIds, Metadatable{
return $this->itemId ?? $this->getId();
}
/**
* @internal
* @return int
*/
public function getRuntimeId() : int{
return BlockFactory::toStaticRuntimeId($this->getId(), $this->getDamage());
}
/**
* @return int
*/
@ -258,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();
@ -269,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;

View File

@ -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){
@ -330,6 +334,10 @@ class BlockFactory{
}
}
public static function isInit() : bool{
return self::$fullList !== null;
}
/**
* Registers a block type into the index. Plugins may use this method to register new block types or override
* existing ones.
@ -411,6 +419,7 @@ class BlockFactory{
* Returns whether a specified block ID is already registered in the block factory.
*
* @param int $id
*
* @return bool
*/
public static function isRegistered(int $id) : bool{
@ -421,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"]);
}
}

View File

@ -23,12 +23,15 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\TieredTool;
class BrewingStand extends Transparent{
protected $id = self::BREWING_STAND_BLOCK;
protected $itemId = Item::BREWING_STAND;
public function __construct(int $meta = 0){
$this->meta = $meta;
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use function mt_rand;
class BrownMushroomBlock extends RedMushroomBlock{

View File

@ -31,7 +31,6 @@ use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\Server;
class Cactus extends Transparent{
@ -95,10 +94,14 @@ class Cactus extends Transparent{
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
if($b->getId() === self::AIR){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
$ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS));
$ev->call();
if($ev->isCancelled()){
break;
}
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
}else{
break;
}
}
$this->meta = 0;

View File

@ -35,6 +35,8 @@ class Cake extends Transparent implements FoodSource{
protected $id = self::CAKE_BLOCK;
protected $itemId = Item::CAKE;
public function __construct(int $meta = 0){
$this->meta = $meta;
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use function mt_rand;
class Carrot extends Crops{

View File

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

View File

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

View File

@ -27,7 +27,7 @@ use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\Server;
use function mt_rand;
abstract class Crops extends Flowable{
@ -43,15 +43,15 @@ 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){
$block->meta = 7;
}
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
$ev = new BlockGrowEvent($this, $block);
$ev->call();
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
}
@ -79,8 +79,8 @@ abstract class Crops extends Flowable{
if($this->meta < 0x07){
$block = clone $this;
++$block->meta;
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
$ev = new BlockGrowEvent($this, $block);
$ev->call();
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), true, true);
}

View File

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

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
class DetectorRail extends Rail{
class DetectorRail extends RedstoneRail{
protected $id = self::DETECTOR_RAIL;

View File

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

View File

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

View File

@ -47,4 +47,8 @@ abstract class DoubleSlab extends Solid{
public function isAffectedBySilkTouch() : bool{
return false;
}
public function getPickedItem() : Item{
return ItemFactory::get($this->getSlabId(), $this->getVariant());
}
}

View File

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

View File

@ -111,4 +111,8 @@ class Farmland extends Transparent{
public function isAffectedBySilkTouch() : bool{
return false;
}
public function getPickedItem() : Item{
return ItemFactory::get(Item::DIRT);
}
}

View File

@ -31,7 +31,8 @@ use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\Server;
use function min;
use function mt_rand;
class Fire extends Flowable{
@ -69,7 +70,7 @@ class Fire extends Flowable{
if($entity instanceof Arrow){
$ev->setCancelled();
}
Server::getInstance()->getPluginManager()->callEvent($ev);
$ev->call();
if(!$ev->isCancelled()){
$entity->setOnFire($ev->getDuration());
}
@ -153,7 +154,8 @@ class Fire extends Flowable{
private function burnBlock(Block $block, int $chanceBound) : void{
if(mt_rand(0, $chanceBound) < $block->getFlammability()){
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockBurnEvent($block, $this));
$ev = new BlockBurnEvent($block, $this);
$ev->call();
if(!$ev->isCancelled()){
$block->onIncinerate();

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use function mt_rand;
class Glowstone extends Transparent{

View File

@ -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{
@ -67,7 +68,8 @@ class Grass extends Solid{
$lightAbove = $this->level->getFullLightAt($this->x, $this->y + 1, $this->z);
if($lightAbove < 4 and BlockFactory::$lightFilter[$this->level->getBlockIdAt($this->x, $this->y + 1, $this->z)] >= 3){ //2 plus 1 standard filter amount
//grass dies
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($this, $this, BlockFactory::get(Block::DIRT)));
$ev = new BlockSpreadEvent($this, $this, BlockFactory::get(Block::DIRT));
$ev->call();
if(!$ev->isCancelled()){
$this->level->setBlock($this, $ev->getNewState(), false, false);
}
@ -86,7 +88,8 @@ class Grass extends Solid{
continue;
}
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($b = $this->level->getBlockAt($x, $y, $z), $this, BlockFactory::get(Block::GRASS)));
$ev = new BlockSpreadEvent($b = $this->level->getBlockAt($x, $y, $z), $this, BlockFactory::get(Block::GRASS));
$ev->call();
if(!$ev->isCancelled()){
$this->level->setBlock($b, $ev->getNewState(), false, false);
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use function mt_rand;
class Gravel extends Fallable{

View File

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

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

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

View File

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

View File

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

View File

@ -31,7 +31,6 @@ use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\Player;
use pocketmine\Server;
class Lava extends Liquid{
@ -107,7 +106,7 @@ class Lava extends Liquid{
$entity->attack($ev);
$ev = new EntityCombustByBlockEvent($this, $entity, 15);
Server::getInstance()->getPluginManager()->callEvent($ev);
$ev->call();
if(!$ev->isCancelled()){
$entity->setOnFire($ev->getDuration());
}

View File

@ -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;
@ -147,8 +148,8 @@ class Leaves extends Transparent{
$this->meta &= 0x03;
$visited = [];
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new LeavesDecayEvent($this));
$ev = new LeavesDecayEvent($this);
$ev->call();
if($ev->isCancelled() or $this->findLog($this, $visited, 0)){
$this->getLevel()->setBlock($this, $this, false, false);
}else{

View File

@ -24,11 +24,16 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Entity;
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{
@ -294,12 +299,16 @@ abstract class Liquid extends Transparent{
protected function flowIntoBlock(Block $block, int $newFlowDecay) : void{
if($this->canFlowInto($block) and !($block instanceof Liquid)){
if($block->getId() > 0){
$this->level->useBreakOn($block);
}
$ev = new BlockSpreadEvent($block, $this, BlockFactory::get($this->getId(), $newFlowDecay));
$ev->call();
if(!$ev->isCancelled()){
if($block->getId() > 0){
$this->level->useBreakOn($block);
}
$this->level->setBlock($block, BlockFactory::get($this->getId(), $newFlowDecay), true, true);
$this->level->scheduleDelayedBlockUpdate($block, $this->tickRate());
$this->level->setBlock($block, $ev->getNewState(), true, true);
$this->level->scheduleDelayedBlockUpdate($block, $this->tickRate());
}
}
}
@ -425,10 +434,12 @@ abstract class Liquid extends Transparent{
}
protected function liquidCollide(Block $cause, Block $result) : bool{
//TODO: add events
$this->level->setBlock($this, $result, 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));
$ev = new BlockFormEvent($this, $result);
$ev->call();
if(!$ev->isCancelled()){
$this->level->setBlock($this, $ev->getNewState(), true, true);
$this->level->addSound(new FizzSound($this->add(0.5, 0.5, 0.5), 2.6 + (lcg_value() - lcg_value()) * 0.8));
}
return true;
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use function mt_rand;
class Melon extends Transparent{

View File

@ -27,7 +27,7 @@ use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\math\Vector3;
use pocketmine\Server;
use function mt_rand;
class MelonStem extends Crops{
@ -46,7 +46,8 @@ class MelonStem extends Crops{
if($this->meta < 0x07){
$block = clone $this;
++$block->meta;
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
$ev = new BlockGrowEvent($this, $block);
$ev->call();
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), true);
}
@ -60,7 +61,8 @@ class MelonStem extends Crops{
$side = $this->getSide(mt_rand(2, 5));
$d = $side->getSide(Vector3::SIDE_DOWN);
if($side->getId() === self::AIR and ($d->getId() === self::FARMLAND or $d->getId() === self::GRASS or $d->getId() === self::DIRT)){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($side, BlockFactory::get(Block::MELON_BLOCK)));
$ev = new BlockGrowEvent($side, BlockFactory::get(Block::MELON_BLOCK));
$ev->call();
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($side, $ev->getNewState(), true);
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\TieredTool;
use function mt_rand;
class MonsterSpawner extends Transparent{

View File

@ -27,7 +27,7 @@ use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\math\Vector3;
use pocketmine\Server;
use function mt_rand;
class Mycelium extends Solid{
@ -67,7 +67,8 @@ class Mycelium extends Solid{
$block = $this->getLevel()->getBlockAt($x, $y, $z);
if($block->getId() === Block::DIRT){
if($block->getSide(Vector3::SIDE_UP) instanceof Transparent){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($block, $this, BlockFactory::get(Block::MYCELIUM)));
$ev = new BlockSpreadEvent($block, $this, BlockFactory::get(Block::MYCELIUM));
$ev->call();
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($block, $ev->getNewState());
}

View File

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

View File

@ -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;
@ -68,8 +69,8 @@ class NetherWartPlant extends Flowable{
if($this->meta < 3 and mt_rand(0, 10) === 0){ //Still growing
$block = clone $this;
$block->meta++;
$this->getLevel()->getServer()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
$ev = new BlockGrowEvent($this, $block);
$ev->call();
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), false, true);
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use function mt_rand;
class Potato extends Crops{

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
class PoweredRail extends Rail{
class PoweredRail extends RedstoneRail{
protected $id = self::POWERED_RAIL;
public function getName() : string{

View File

@ -27,7 +27,7 @@ use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\math\Vector3;
use pocketmine\Server;
use function mt_rand;
class PumpkinStem extends Crops{
@ -46,7 +46,8 @@ class PumpkinStem extends Crops{
if($this->meta < 0x07){
$block = clone $this;
++$block->meta;
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($this, $block));
$ev = new BlockGrowEvent($this, $block);
$ev->call();
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($this, $ev->getNewState(), true);
}
@ -60,7 +61,8 @@ class PumpkinStem extends Crops{
$side = $this->getSide(mt_rand(2, 5));
$d = $side->getSide(Vector3::SIDE_DOWN);
if($side->getId() === self::AIR and ($d->getId() === self::FARMLAND or $d->getId() === self::GRASS or $d->getId() === self::DIRT)){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($side, BlockFactory::get(Block::PUMPKIN)));
$ev = new BlockGrowEvent($side, BlockFactory::get(Block::PUMPKIN));
$ev->call();
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($side, $ev->getNewState(), true);
}

View File

@ -23,54 +23,71 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\Player;
class Rail extends Flowable{
class Rail extends BaseRail{
public const STRAIGHT_NORTH_SOUTH = 0;
public const STRAIGHT_EAST_WEST = 1;
public const ASCENDING_EAST = 2;
public const ASCENDING_WEST = 3;
public const ASCENDING_NORTH = 4;
public const ASCENDING_SOUTH = 5;
/* extended meta values for regular rails, to allow curving */
public const CURVE_SOUTHEAST = 6;
public const CURVE_SOUTHWEST = 7;
public const CURVE_NORTHWEST = 8;
public const CURVE_NORTHEAST = 9;
protected $id = self::RAIL;
private const CURVE_CONNECTIONS = [
self::CURVE_SOUTHEAST => [
Vector3::SIDE_SOUTH,
Vector3::SIDE_EAST
],
self::CURVE_SOUTHWEST => [
Vector3::SIDE_SOUTH,
Vector3::SIDE_WEST
],
self::CURVE_NORTHWEST => [
Vector3::SIDE_NORTH,
Vector3::SIDE_WEST
],
self::CURVE_NORTHEAST => [
Vector3::SIDE_NORTH,
Vector3::SIDE_EAST
]
];
public function __construct(int $meta = 0){
$this->meta = $meta;
}
protected $id = self::RAIL;
public function getName() : string{
return "Rail";
}
public function getHardness() : float{
return 0.7;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if(!$blockReplace->getSide(Vector3::SIDE_DOWN)->isTransparent()){
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
}
return false;
}
public function onNearbyBlockChange() : void{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
$this->getLevel()->useBreakOn($this);
}else{
//TODO: Update rail connectivity
protected function getMetaForState(array $connections) : int{
try{
return self::searchState($connections, self::CURVE_CONNECTIONS);
}catch(\InvalidArgumentException $e){
return parent::getMetaForState($connections);
}
}
public function getVariantBitmask() : int{
return 0;
protected function getConnectionsForState() : array{
return self::CURVE_CONNECTIONS[$this->meta] ?? self::CONNECTIONS[$this->meta];
}
protected function getPossibleConnectionDirectionsOneConstraint(int $constraint) : array{
static $horizontal = [
Vector3::SIDE_NORTH,
Vector3::SIDE_SOUTH,
Vector3::SIDE_WEST,
Vector3::SIDE_EAST
];
$possible = parent::getPossibleConnectionDirectionsOneConstraint($constraint);
if(($constraint & self::FLAG_ASCEND) === 0){
foreach($horizontal as $d){
if($constraint !== $d){
$possible[$d] = true;
}
}
}
return $possible;
}
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use function mt_rand;
class RedMushroomBlock extends Solid{

View File

@ -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{
@ -50,7 +51,8 @@ class RedstoneOre extends Solid{
}
public function onActivate(Item $item, Player $player = null) : bool{
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::GLOWING_REDSTONE_ORE, $this->meta));
$this->getLevel()->setBlock($this, BlockFactory::get(Block::GLOWING_REDSTONE_ORE, $this->meta));
return false; //this shouldn't prevent block placement
}
public function onNearbyBlockChange() : void{

View File

@ -0,0 +1,32 @@
<?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 RedstoneRail extends BaseRail{
protected const FLAG_POWERED = 0x08;
protected function getConnectionsForState() : array{
return self::CONNECTIONS[$this->meta & ~self::FLAG_POWERED];
}
}

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

View File

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

View File

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

View File

@ -71,18 +71,20 @@ class Skull extends Flowable{
return true;
}
public function getDropsForCompatibleTool(Item $item) : array{
private function getItem() : Item{
$tile = $this->level->getTile($this);
if($tile instanceof TileSkull){
return [
ItemFactory::get(Item::SKULL, $tile->getType())
];
}
return ItemFactory::get(Item::SKULL, $tile instanceof TileSkull ? $tile->getType() : 0);
}
return [];
public function getDropsForCompatibleTool(Item $item) : array{
return [$this->getItem()];
}
public function isAffectedBySilkTouch() : bool{
return false;
}
public function getPickedItem() : Item{
return $this->getItem();
}
}

View File

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

View File

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

View File

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

View File

@ -27,7 +27,6 @@ use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\Server;
class Sugarcane extends Flowable{
@ -49,10 +48,13 @@ class Sugarcane extends Flowable{
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
if($b->getId() === self::AIR){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, BlockFactory::get(Block::SUGARCANE_BLOCK)));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
$ev = new BlockGrowEvent($b, BlockFactory::get(Block::SUGARCANE_BLOCK));
$ev->call();
if($ev->isCancelled()){
break;
}
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
}else{
break;
}
}

View File

@ -30,6 +30,9 @@ 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{

View File

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

View File

@ -100,11 +100,7 @@ abstract class Thin extends Transparent{
}
//FIXME: currently there's no proper way to tell if a block is a full-block, so we check the bounding box size
$bbs = $block->getCollisionBoxes();
if(count($bbs) === 1){
return $bbs[0]->getAverageEdgeLength() >= 1;
}
return false;
$bb = $block->getBoundingBox();
return $bb !== null and $bb->getAverageEdgeLength() >= 1;
}
}

View File

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

View File

@ -31,6 +31,10 @@ class UnknownBlock extends Transparent{
return 0;
}
public function canBePlaced() : bool{
return false;
}
public function getDrops(Item $item) : array{
return [];
}

View File

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

View File

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

View File

@ -25,6 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use function mt_rand;
class Wheat extends Crops{

View File

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

View File

@ -27,7 +27,7 @@ namespace pocketmine\command;
interface CommandMap{
/**
* @param string $fallbackPrefix
* @param string $fallbackPrefix
* @param Command[] $commands
*/
public function registerAll(string $fallbackPrefix, array $commands);

View File

@ -25,6 +25,23 @@ 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{
@ -47,9 +64,9 @@ class CommandReader extends Thread{
$this->buffer = new \Threaded;
$this->notifier = $notifier;
$opts = getopt("", ["disable-readline"]);
$opts = getopt("", ["disable-readline", "enable-readline"]);
if(extension_loaded("readline") and !isset($opts["disable-readline"]) and !$this->isPipe(STDIN)){
if(extension_loaded("readline") and (Utils::getOS() === "win" ? isset($opts["enable-readline"]) : !isset($opts["disable-readline"])) and !$this->isPipe(STDIN)){
$this->type = self::TYPE_READLINE;
}
}
@ -94,6 +111,7 @@ class CommandReader extends Thread{
* Checks if the specified stream is a FIFO pipe.
*
* @param resource $stream
*
* @return bool
*/
private function isPipe($stream) : bool{

View File

@ -54,6 +54,7 @@ interface CommandSender extends Permissible{
/**
* Sets the line height used for command output pagination for this command sender. `null` will reset it to default.
*
* @param int|null $height
*/
public function setScreenLineHeight(int $height = null);

View File

@ -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{
@ -64,7 +67,7 @@ class ConsoleCommandSender implements CommandSender{
/**
* @param Plugin $plugin
* @param string $name
* @param bool $value
* @param bool $value
*
* @return PermissionAttachment
*/

View File

@ -23,9 +23,13 @@ declare(strict_types=1);
namespace pocketmine\command;
use pocketmine\lang\TranslationContainer;
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 = [];
@ -49,11 +53,6 @@ class FormattedCommandAlias extends Command{
$commands[] = $this->buildCommand($formatString, $args);
}catch(\InvalidArgumentException $e){
$sender->sendMessage(TextFormat::RED . $e->getMessage());
return false;
}catch(\Throwable $e){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.exception"));
$sender->getServer()->getLogger()->logException($e);
return false;
}
}

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\command;
use pocketmine\lang\TextContainer;
use function trim;
class RemoteConsoleCommandSender extends ConsoleCommandSender{

View File

@ -65,9 +65,17 @@ use pocketmine\command\defaults\VanillaCommand;
use pocketmine\command\defaults\VersionCommand;
use pocketmine\command\defaults\WhitelistCommand;
use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\lang\TranslationContainer;
use pocketmine\Server;
use pocketmine\utils\TextFormat;
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{
@ -92,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"),
@ -114,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"),
@ -124,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")
]);
}
}
@ -193,9 +196,9 @@ class SimpleCommandMap implements CommandMap{
/**
* @param Command $command
* @param bool $isAlias
* @param string $fallbackPrefix
* @param string $label
* @param bool $isAlias
* @param string $fallbackPrefix
* @param string $label
*
* @return bool
*/
@ -244,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);
@ -258,14 +270,10 @@ class SimpleCommandMap implements CommandMap{
$target->execute($sender, $sentCommandLabel, $args);
}catch(InvalidCommandSyntaxException $e){
$sender->sendMessage($this->server->getLanguage()->translateString("commands.generic.usage", [$target->getUsage()]));
}catch(\Throwable $e){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.exception"));
$this->server->getLogger()->critical($this->server->getLanguage()->translateString("pocketmine.command.exception", [$commandLine, (string) $target, $e->getMessage()]));
$sender->getServer()->getLogger()->logException($e);
}finally{
$target->timings->stopTiming();
}
$target->timings->stopTiming();
return true;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\command\defaults;
use pocketmine\command\CommandSender;
use function date;
class DumpMemoryCommand extends VanillaCommand{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More