Compare commits

...

620 Commits
3.0.8 ... 3.5.5

Author SHA1 Message Date
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
1193efd69e Release 3.2.1 2018-08-31 18:58:53 +01:00
2738e38aee Merge branch 'release/3.2' into release/3.3 2018-08-31 16:19:52 +01:00
f466fd5568 Updated runtime IDs table
apparently 1 (!) missing entry (for barrier) was causing client sided crashes unexplained. This is infuriating.
2018-08-31 16:19:42 +01:00
72d447276b Merge branch 'release/3.2' into release/3.3 2018-08-30 15:46:54 +01:00
d5a5209334 Merge branch 'release/3.1' into release/3.2 2018-08-30 15:46:46 +01:00
3a85e6cab9 Backport ce58294305 for 3.x line 2018-08-30 15:46:26 +01:00
d0aff2ecbd Bump version for 3.3 dev branch 2018-08-30 11:05:58 +01:00
bca493a682 3.2.1 is next 2018-08-30 11:04:47 +01:00
ba12dfafd6 Release 3.2.0 2018-08-29 16:28:35 +01:00
e09087de26 Fix version numbers 2018-08-29 16:27:01 +01:00
888dba704b Merge branch 'mcpe-1.6' into release/3.2 2018-08-29 16:23:53 +01:00
511249c562 Sync 3.2 and 3.1 branches 2018-08-29 16:23:28 +01:00
17f1bf5512 3.1.6 is next 2018-08-29 16:08:45 +01:00
5179bb1d30 Release 3.1.5 2018-08-29 15:57:58 +01:00
6bff840293 Sync 3.1 and 3.0 branches 2018-08-29 15:55:14 +01:00
08897c6941 Release 3.0.12 2018-08-29 15:47:28 +01:00
05d9bb45d0 Merge branch 'release/3.1' into release/3.2 2018-08-26 19:15:16 +01:00
dfe2aa9c67 Merge branch 'release/3.0' into release/3.1 2018-08-26 19:15:08 +01:00
4006be35d9 Update BinaryUtils dependency 2018-08-26 19:15:01 +01:00
e5cda34548 Merge branch 'release/3.1' into mcpe-1.6 2018-08-26 18:05:14 +01:00
032b20f659 Server: remove premature optimization of findEntity() 2018-08-25 18:37:18 +01:00
fe6d546190 Merge branch 'release/3.1' into release/3.2 2018-08-25 17:49:21 +01:00
c7af1cf785 Merge branch 'release/3.0' into release/3.1 2018-08-25 17:49:14 +01:00
22fcfffa53 PluginsCommand: remove useless private function 2018-08-25 16:09:51 +01:00
7dd53f2397 Replace unnecessary strlen > 0 calls with !== "" checks 2018-08-25 16:07:49 +01:00
298259b473 PluginsCommand: clean up garbage code 2018-08-25 16:05:25 +01:00
c123f2d10b SimpleCommandMap: clean up error reporting in registerServerAliases() 2018-08-25 15:43:23 +01:00
3e6f70ddf6 Merge branch 'release/3.1' into mcpe-1.6 2018-08-23 18:00:06 +01:00
bea634a9b7 Change air tank regeneration to match UA (#2396) 2018-08-22 19:10:53 +01:00
8daf3dc8b4 Merge branch 'release/3.1' into release/3.2 2018-08-22 15:41:52 +01:00
4cc7573a64 Merge branch 'release/3.0' into release/3.1 2018-08-22 15:40:43 +01:00
9d80802e53 Living: fixed some update conditions not being set 2018-08-22 15:40:32 +01:00
ec1e257e21 Entity: Fixed fire damage not taking effect in the void
this is an absurd bug that nobody would ever otherwise notice, but the problem is that the doOnFireTick() call isn't evaluated if hasUpdate is already true.
2018-08-22 15:36:31 +01:00
d419d4308f Add a couple of item constants, register Scute item
leaving out turtle helmet for now because of complications relating to the effect application - I REALLY don't want to tick armour if I can avoid it, due to the performance concerns.
2018-08-21 19:54:24 +01:00
9ca38ba868 Protocol changes for 1.6.0.8 + resource packs "fix" 2018-08-21 17:36:55 +01:00
424c50e1e9 Protocol changes for 1.6.0.5, minus Entity->Actor rename 2018-08-21 17:36:29 +01:00
566f3c6262 AvailableCommandsPacket: stricter decode and handling 2018-08-21 17:14:54 +01:00
0d05dcec08 AvailableCommandsPacket: deal with dynamic enums
somehow I missed this, thanks @NiclasOlofsson for pointing it out
2018-08-21 17:14:53 +01:00
986077e03c Protocol changes for 1.6.0.1 2018-08-21 17:14:53 +01:00
ddcb2f002a Tile: Be explicit about not calling Tile::createNBT() (#2388)
A common pitfall developers fall into with this function is that it has to be called from the scope of the tile class you're creating NBT for, but people commonly do Tile::createNBT() directly, which then results in cryptic "Tile is not registered" errors. This now throws a BadMethodCallException instead to be fully clear about this.

In the future this will be removed completely once NBT is no longer required to create a tile, but for now this is a confusing issue that should be dealt with.
2018-08-19 19:54:22 +01:00
c496480d2b Merge branch 'release/3.1' into release/3.2 2018-08-19 19:52:40 +01:00
6fce2b3349 Merge branch 'release/3.0' into release/3.1 2018-08-19 19:52:30 +01:00
64ed8adefc Cactus: fixed place/break logic mismatch causing item spewing 2018-08-19 19:52:07 +01:00
2eda8cfad3 Merge branch 'release/3.1' into release/3.2 2018-08-19 16:01:47 +01:00
91be5aba0c Merge branch 'release/3.0' into release/3.1 2018-08-19 16:00:25 +01:00
5df601c817 Add @see docs so PhpStorm can see dynamic constructor usages
PhpStorm can't see constructor usages when the class name is dynamic. This causes maintenance problems because cross-referencing constructors called like this doesn't show up dynamic calls.
2018-08-19 16:00:15 +01:00
21e7b5ea43 TesterPlugin: removed usage of deprecated ServerCommandEvent 2018-08-19 14:05:26 +01:00
8304675af7 Merge branch 'release/3.1' into release/3.2 2018-08-19 13:59:58 +01:00
1a47735d84 Merge branch 'release/3.0' into release/3.1 2018-08-19 13:59:34 +01:00
0cdf4d0c55 Spoon the TesterPlugin into the main repository
I am eating my own words this once, because having the tester plugin as a separate repository makes no sense - it is just added barriers to writing proper tests with no actual benefit. Since the tester plugin is specifically intended for CI, it doesn't make sense for it to be in its own module.
2018-08-19 13:58:13 +01:00
e6e28b74b5 Nuke the TesterPlugin submodule 2018-08-19 13:47:43 +01:00
ebffff0caa Added CommandEvent, deprecated (Remote)?ServerCommandEvent (#2376) 2018-08-19 12:59:16 +01:00
0dc4bd36e1 Form: change handleResponse() return type to void
this returning is counter intuitive and doesn't make any sense without the queuing mechanism. Instead it's simpler to just use Player->sendForm().
2018-08-19 11:44:59 +01:00
9d17c9a09d Merge branch 'release/3.1' into release/3.2 2018-08-19 11:22:58 +01:00
72f46b4631 Merge branch 'release/3.0' into release/3.1 2018-08-19 11:22:51 +01:00
3892f2f404 Config: Properly prevent keys getting transformed into bools
The original regex almost completely failed at its objective, because it a) only worked if there was no value for the key, and b) did not prevent all such occurrences getting transformed, while quoting patterns that would not get transformed anyway.
2018-08-19 11:22:36 +01:00
bfa415e108 Add unit tests for json decoding hack 2018-08-19 10:30:52 +01:00
b66095cb36 Added a hack for MC W10 JSON empty strings bug (#2383) 2018-08-19 10:10:40 +01:00
0336ae8229 Merge branch 'release/3.1' into release/3.2 2018-08-17 19:47:41 +01:00
4a1d67cb91 Merge branch 'release/3.0' into release/3.1 2018-08-17 19:47:34 +01:00
b4694092b7 Painting: fix motive not being saved 2018-08-17 19:47:26 +01:00
4b3e17e681 Sync 3.2 and 3.1 branches 2018-08-16 18:33:54 +01:00
d99ee515c6 3.1.5 is next 2018-08-16 18:33:27 +01:00
17f7dc34be Release 3.1.4 2018-08-16 18:26:49 +01:00
a63d66c048 Sync 3.1 and 3.0 branches 2018-08-16 18:26:26 +01:00
95f6995ae0 3.0.12 is next 2018-08-16 18:25:31 +01:00
4a24d7909e Release 3.0.11 2018-08-16 18:14:04 +01:00
5424644ca1 Merge branch 'release/3.1' into release/3.2 2018-08-16 15:52:19 +01:00
4e2387edc1 Merge branch 'release/3.0' into release/3.1 2018-08-16 15:52:12 +01:00
a5e38576ef ItemEntity: fixed using -1 for infinite pickup delay not working
closes #2382 (squash-merge)
2018-08-16 15:52:05 +01:00
aa7c4bc64d Merge branch 'release/3.1' into release/3.2 2018-08-15 13:48:46 +01:00
381151dedc Merge branch 'release/3.0' into release/3.1 2018-08-15 13:48:36 +01:00
a604e6835e CoalOre: fixed ignoring silk touch for XP drops, closes #2374 2018-08-15 13:48:29 +01:00
df8e10cad9 Forms API, part 1: add Player->sendForm() and Form interface
There's no implementation here yet, but that can come later. This lays the ground for allowing plugins to have an integrated method to send forms, as well as a solution to the ID conflict problem.

A built in implementation should not be a concretion and it should be able to be swapped for third party implementations. This enables the possiblity to do so.
2018-08-14 16:06:55 +01:00
d98a6e566c Merge branch 'release/3.1' into release/3.2 2018-08-14 15:03:30 +01:00
142a6d7678 Merge branch 'release/3.0' into release/3.1 2018-08-14 15:03:22 +01:00
b2ca364de0 SplashPotion: Don't apply effects to entities which are not alive
fixes #2372
2018-08-14 15:03:15 +01:00
ade2be9eee Merge branch 'release/3.1' into release/3.2 2018-08-13 13:22:40 +01:00
09ed40a921 Merge branch 'release/3.0' into release/3.1 2018-08-13 13:22:32 +01:00
565373cee6 OfflinePlayer: remove unnecessary getName() usages 2018-08-13 13:22:00 +01:00
c29723e3c4 OfflinePlayer: remove unnecessary strtolower() calls
closes #2371
2018-08-13 13:18:58 +01:00
39ed6a7cdf Merge branch 'release/3.1' into release/3.2 2018-08-11 19:59:53 +01:00
a8811ab2b3 Fixed 1.5.0 PlayerSkinPacket protocol change that somehow disappeared
I am 100% sure I committed this change, but it isn't in the merge...
2018-08-11 19:59:44 +01:00
bec5aaa54b Merge branch 'release/3.1' into release/3.2 2018-08-11 19:37:18 +01:00
974583a853 Merge branch 'release/3.0' into release/3.1 2018-08-11 19:37:10 +01:00
03f8fe62d4 Fixed structure of GuiDataPickItemPacket
this changed in 1.2.0.7 beta and I didn't spot it.
2018-08-11 19:36:53 +01:00
cf29ab1f17 Arrow: remove unused import 2018-08-07 19:06:40 +01:00
c5c5a53a13 Merge branch 'release/3.1' into release/3.2 2018-08-07 18:49:13 +01:00
699f35cc05 Merge branch 'release/3.0' into release/3.1 2018-08-07 18:49:06 +01:00
8fa196efc9 FallingBlock: fixed state not being saved 2018-08-07 18:48:52 +01:00
63a65680ac typo 2018-08-07 14:43:29 +01:00
47cd6fe105 EntityDamageEvent: Add API to customize Living entity attack cooldown time
closes #2310
2018-08-07 14:39:26 +01:00
f582b5a3db Merge branch 'release/3.1' into release/3.2 2018-08-07 14:32:38 +01:00
b1ab881b99 Merge branch 'release/3.0' into release/3.1 2018-08-07 14:32:28 +01:00
69c54e789a Clear the title bar when the server shutdown. 2018-08-07 14:31:39 +01:00
7f0fa2ac3d PluginBase: Do not fill defaults from resources/config.yml (#2316)
This fixes #2219.
2018-08-07 12:33:24 +01:00
max
f3b2bcfd13 Added Conduit Power effect 2018-08-06 21:30:15 +01:00
c947909c2e Updated language submodule 2018-08-06 20:52:53 +01:00
09dadc72bc Merge branch 'release/3.1' into release/3.2 2018-08-06 18:45:08 +01:00
e33d1279fa Merge branch 'release/3.0' into release/3.1 2018-08-06 18:45:01 +01:00
9e1fa453ad Level: Fixed leak of global packets when no players are online
If a global packet was broadcasted when no players were online, it would be held in memory indefinitely (until a player joined).
2018-08-06 18:44:53 +01:00
ca541032ae Move Player death message derivation to PlayerDeathEvent static method
This now no longer requires a Player to operate, only a player name.
2018-08-05 12:19:16 +01:00
bcf9915082 Merge branch 'release/3.1' into release/3.2 2018-08-05 11:33:11 +01:00
6a05edb4e9 Merge branch 'release/3.0' into release/3.1 2018-08-05 11:33:02 +01:00
70635d0870 DropItemAction: Consider invalid if the target item is null
it's not possible to drop a null item.
2018-08-05 11:32:50 +01:00
8d6dc4e188 Merge branch 'release/3.1' into release/3.2 2018-08-04 16:47:26 +01:00
46bd096f06 3.1.4 is next 2018-08-04 16:46:51 +01:00
51a8905fb3 Release 3.1.3 2018-08-04 16:41:16 +01:00
f954d7c3dc Bring 3.1 up to speed with 3.0 2018-08-04 16:40:40 +01:00
7ad0aa56b1 3.0.11 is next 2018-08-04 16:39:53 +01:00
1ff6f8846e disable dev flag 2018-08-04 16:30:23 +01:00
12d8d925c8 TimingsCommand: check for instances of InternetException only 2018-08-04 14:59:31 +01:00
f3f229ef7c Internet: only catch InternetExceptions - anything else is an unexpected fault condition 2018-08-04 14:51:26 +01:00
6614183c7f Merge branch 'release/3.1' into release/3.2 2018-08-03 20:07:52 +01:00
e6f53cc56b Merge branch 'release/3.0' into release/3.1 2018-08-03 20:07:46 +01:00
87f458f9bd AsyncPool: remove now-unnecessary isTerminated() call 2018-08-03 20:07:37 +01:00
5a7e575c3a AsyncPool: isCrashed() now returns true when a fatal error occurred
the fix for chunks earlier didn't fix...
2018-08-03 20:06:41 +01:00
7ebf3c7bf4 Merge branch 'release/3.1' into release/3.2 2018-08-03 18:50:22 +01:00
20b37d0208 Merge branch 'release/3.0' into release/3.1 2018-08-03 18:50:14 +01:00
d6d98183ea MainLogger: Log messages and exception traces in a synchronized block
this ensures that stack traces are emitted coherently without messages from other threads landing in the middle.
2018-08-03 18:50:06 +01:00
334caaaa34 Merge branch 'release/3.1' into release/3.2 2018-08-03 18:24:44 +01:00
89cf76363f Merge branch 'release/3.0' into release/3.1 2018-08-03 18:24:36 +01:00
9ff5c65fb6 Level: Make async chunk sending aware of faults
Previously any random error could occur during an AsyncTask preparing a chunk, and the Level would never know about it and thus never send the chunk.

I don't know how many invisible-chunk bug cases this fixes, but I expect it's quite a lot.
2018-08-03 18:23:32 +01:00
1532b0ef6d Level: Remove chunks from chunk send queue on unload
When a chunk request task crashes, these can get stuck and never get removed. This allows using /gc to collect the bad chunk in order to fix the bug.
2018-08-03 18:04:56 +01:00
6fcaef068f Merge branch 'release/3.1' into release/3.2 2018-08-02 14:43:51 +01:00
61accee682 Merge branch 'release/3.0' into release/3.1 2018-08-02 14:43:44 +01:00
9ece971a2b Server: remove useless check from exceptionHandler()
this cannot be null... @shoghicp y u litter the code with these useless checks ???
2018-08-02 14:41:28 +01:00
5546c88f88 Server: Fixed parse errors getting reported to CA
this changed to throwing errors as of PHP 7
2018-08-02 14:40:36 +01:00
c09ad9263b Empty merge of 3.1 into 3.2 2018-07-30 15:21:42 +01:00
4c4761d200 back to dev 2018-07-30 15:21:10 +01:00
5492495d38 disable dev flag 2018-07-30 15:10:12 +01:00
6bef07db7c Empty merge of 3.0 into 3.1 2018-07-30 15:09:53 +01:00
e8c7ae595d back to dev 2018-07-30 15:08:32 +01:00
0d9f40873f disable dev flag 2018-07-30 14:57:51 +01:00
4cc2f037a9 Merge branch 'release/3.1' into release/3.2 2018-07-30 14:54:10 +01:00
f7358cd7e1 Merge branch 'release/3.0' into release/3.1 2018-07-30 14:54:01 +01:00
a4aee98cba TimingsCommand: some code cleanup 2018-07-30 14:53:10 +01:00
a97c7d3132 Fix for timings 2018-07-30 14:42:16 +01:00
99045fe21a Entity: Implement setting score tag 2018-07-30 09:36:32 +01:00
bda271ca63 Merge branch 'release/3.1' into release/3.2 2018-07-27 11:47:36 +01:00
808d289610 Merge branch 'release/3.0' into release/3.1 2018-07-27 11:47:22 +01:00
4a1ed21e52 PluginManager: Fix patch level check to allow loading the plugin when the server's minor level is higher than the plugins declared minor level. 2018-07-27 11:46:24 +01:00
b3f2396ea5 UPnP: Make error message less useless 2018-07-26 16:00:35 +01:00
ab0510cb37 Merge branch 'release/3.1' into release/3.2 2018-07-26 14:40:33 +01:00
06c035bfe6 Merge branch 'release/3.0' into release/3.1 2018-07-26 14:40:24 +01:00
1b053c7928 Clean up pointless checks in Thread/Worker 2018-07-26 14:20:55 +01:00
c684f99cc4 Clean up Thread/Worker quit() 2018-07-26 14:17:01 +01:00
9a423be1db Internet: Throw more specific exceptions
RuntimeException is very generic and might be thrown for other reasons apart from web request failures.

This is backwards compatible because InternetException is a descendent of RuntimeException. Additionally, getURL() and postURL() have intentionally been left untouched for backwards compatibility's sake.
2018-07-26 12:34:14 +01:00
08be51dc23 Clear permissions on server reload 2018-07-26 10:40:28 +01:00
94352782d5 https://media.giphy.com/media/UAUtB4Oi9U4EM/giphy.gif 2018-07-26 10:31:57 +01:00
8fae79f85b Merge branch 'release/3.1' into release/3.2 2018-07-26 10:25:19 +01:00
8d47a222b4 Merge branch 'release/3.0' into release/3.1 2018-07-26 10:25:13 +01:00
695793795e PluginManager: Remove dead $pluginParentTimer left over from 9e4d88a852 2018-07-26 10:25:01 +01:00
9a2845640b Permissions management cleanup (#2332)
* Added a new PermissionManager, remove ridiculous cyclic dependencies of Permissions on Server

Aside from all the other ridiculous design problems with the permission system, the biggest problems are its API. This is, once again, a result of poor API design copied from Bukkit.

This pull request removes all permission-related functionality from `PluginManager` and moves it to the `pocketmine\permission\PermissionManager` class.

As can be observed from the removed code in the diff, the permissions system was previously entirely dependent on the Server, because it needed to get the PluginManager for registering permissions. This is utterly ridiculous. This refactor isolates _most_ permission-related functionality within the `permission` namespace.

As mentioned above, this stupid API is a direct result of copying from Bukkit. If you look at the API documentation for Bukkit for `PluginManager` you will see that the methods I'm deprecating here are also in there.

## Changes
- Added a new `PermissionManager` class. This can be accessed via its singleton `getInstance()` static method.
- Deprecated the following `PluginManager` methods - these will be removed no later than 4.0.0:
  - `getPermission()`
  - `addPermission()`
  - `removePermission()`
  - `getDefaultPermissions()`
  - `recalculatePermissionDefaults()`
  - `subscribeToPermission()`
  - `unsubscribeFromPermission()`
  - `getPermissionSubscriptions()`
  - `subscribeToDefaultPerms()`
  - `unsubscribeFromDefaultPerms()`
  - `getDefaultPermSubscriptions()`
  - `getPermissions()`
2018-07-26 10:21:41 +01:00
580f71d496 Permission: cosmetic reorg 2018-07-25 20:56:23 +01:00
24f11779f2 Level: don't try to unregister generators from non-live workers
this was causing garbage-collected workers to get restarted on shutdown if they previously had the generator registered for that level.
2018-07-25 18:52:17 +01:00
706c620d04 Move Internet-related functions from Utils into their own class (#2324)
- Added `Internet::getIP()`, `Internet::getURL()`, `Internet::postURL()`, and `Internet::simpleCurl()`.
- Deprecated the corresponding functions in `Utils`. Updating to the new functions is as simple as replacing `Utils` with `Internet`, since this doesn't break backwards compatibility.

The deprecations should be catered for by plugin developers. These deprecated redirects will be removed no later than 4.0.0.
2018-07-25 15:51:18 +01:00
951870e6ec Merge branch 'release/3.1' into release/3.2 2018-07-25 15:30:40 +01:00
9f425bbe2b Merge branch 'release/3.0' into release/3.1 2018-07-25 15:30:31 +01:00
a4965842d6 Remove $handlerList from PlayerExperienceChangeEvent 2018-07-25 15:30:01 +01:00
1405099768 Merge branch 'release/3.1' into release/3.2 2018-07-24 17:19:18 +01:00
d0339796b4 Added DATA_FLAG_SHOW_TRIDENT_ROPE 2018-07-24 17:19:06 +01:00
1464487945 Utils: remove unnecessary do...while(false) from getIP() 2018-07-24 16:33:03 +01:00
40c28f4d26 PluginManager: Automatically create data directories for plugins (#2284) 2018-07-21 15:57:37 +01:00
90bf94f8f7 Merge branch 'release/3.1' into release/3.2 2018-07-21 09:53:41 +01:00
5e13e2e777 Merge branch 'release/3.0' into release/3.1 2018-07-21 09:53:31 +01:00
1ef6f5d166 ZippedResourcePack: Make manifest parse errors less useless 2018-07-21 09:53:16 +01:00
eccc249009 KillCommand: clean up old shitcode 2018-07-20 19:44:41 +01:00
522ef042a7 yet another empty merge... this is tiresome 2018-07-20 12:21:49 +01:00
4be36914d6 back to dev 2018-07-20 12:21:15 +01:00
e3ef1ecb30 another empty merge 2018-07-20 12:20:54 +01:00
dbaf7287bc back to dev 2018-07-20 12:20:24 +01:00
3640062142 disable dev flag 2018-07-20 12:12:26 +01:00
9af70283fd Empty merge 2018-07-20 12:11:58 +01:00
76ee6bc298 Merge branch 'release/3.1' into release/3.2 2018-07-20 11:57:13 +01:00
b18872fbc6 Merge branch 'release/3.0' into release/3.1 2018-07-20 11:57:06 +01:00
04f20c703c Merge branch 'release/3.1' into release/3.2 2018-07-20 11:30:39 +01:00
dd8499e202 Merge branch 'release/3.0' into release/3.1 2018-07-20 11:30:27 +01:00
efe4b0cd3a Merge branch 'release/3.1' into release/3.2 2018-07-18 15:14:34 +01:00
4d1e56069d Merge branch 'release/3.0' into release/3.1 2018-07-18 15:14:27 +01:00
527d8e9374 Merge branch 'release/3.1' into release/3.2 2018-07-17 18:35:16 +01:00
c1c70a8a98 move up a version
pushing this back to 3.2 so that we can make space for MCPE 1.5 line as 3.1.
2018-07-17 18:34:55 +01:00
45d30d53cc back to dev 2018-07-17 18:33:36 +01:00
cfc8dfa369 disable dev flag 2018-07-17 18:21:02 +01:00
93a2f397c6 Merge branch 'mc-broken-ed-1.5' into release/3.1 2018-07-17 18:13:06 +01:00
62fc875cdc bump version 2018-07-17 18:12:49 +01:00
b7f15b6574 Merge branch 'release/3.0' into release/3.1 2018-07-17 16:56:57 +01:00
6ab2fa84da added some tests for ItemFactory::fromString() 2018-07-17 14:52:47 +01:00
b480c63060 Fixed ItemFactory::fromString() meta handling bug introduced by 71c3c34976 2018-07-17 14:46:08 +01:00
f6b54f5116 Server: don't create levels inside catch-all
Under normal circumstances, none of the boxed code will throw exceptions. Under exceptional circumstances, the caller should know about it. Usually the caller is the server. We don't want to catch unexpected exceptions because those should crash the server and generate a crashdump.
2018-07-17 12:18:46 +01:00
89bfc380e3 Merge branch 'release/3.0' into release/3.1 2018-07-17 12:14:33 +01:00
40030e9800 added some LevelProviderManager tests 2018-07-17 12:02:08 +01:00
ad1cf38c21 LevelProviderManager: tighten up checks on registering 2018-07-17 12:02:08 +01:00
5d769147ca LevelProviderManager: make addProvider() throw InvalidArgumentException instead of LevelException
LevelException is not useful because it's too generic.
2018-07-17 12:02:08 +01:00
6f00a30ad7 Merge branch 'release/3.0' into release/3.1 2018-07-17 10:12:52 +01:00
b4bf6901e3 Server: remove useless try/catch around Query event firing
this doesn't raise any exceptions, and if it causes Errors to be thrown, those are defects that should be fixed. A catch-all is a bad thing.
2018-07-17 10:10:28 +01:00
71c3c34976 ItemFactory: prepare for handling items with negative IDs 2018-07-16 13:24:12 +01:00
16c253d7a9 Item: allow negative IDs
this will be needed in the future for extended blocks support.
2018-07-16 12:46:16 +01:00
7efe767f1f Merge branch 'release/3.0' into release/3.1 2018-07-16 12:08:22 +01:00
2e18fe710c MemoryManager: Shut down idle workers during GC to reclaim memory
workers can be a major memory hog, especially if you have lots of them.
2018-07-14 18:07:37 +01:00
165aac1ba3 Merge branch 'release/3.0' into mc-broken-ed-1.5 2018-07-14 16:09:57 +01:00
878dd3b842 Merge branch 'release/3.0' into release/3.1 2018-07-14 16:06:02 +01:00
478a131aa5 Flat: separate logic of parsing preset and generating base chunk
now always generates the base chunk on init, because the generator won't be created unless there is generation to be done.
2018-07-14 11:51:49 +01:00
53068caf3c Level: Only register generators when attempting to actually generate chunks
This saves a ton of memory on servers which don't generate any chunks during their runtime (which is most servers).
2018-07-14 11:34:55 +01:00
fe7ad7a5b3 Merge branch 'release/3.0' into release/3.1 2018-07-14 10:39:28 +01:00
24f749a933 Merge branch 'release/3.0' into release/3.1 2018-07-13 12:36:10 +01:00
af80aefd45 Remove async config save (#2298)
As discussed in #2297:

Honestly I don't see a fit purpose for async saving at all. It should either always be synchronous or always asynchronous, and at the user's own option. However, this isn't currently possible because Config doesn't enable you to get the serialized content without writing it to disk.

Consider the following code:
```php
		for($i = 0, $size = $this->getServer()->getAsyncPool()->getSize(); $i < $size; ++$i){
			$this->getServer()->getAsyncPool()->submitTask(new class extends AsyncTask{
				public function onRun(){
					sleep(5);
				}
			});
		}
		$config = $this->getConfig();
		$config->set("steve", "hi");
		$config->save(true);
		$config->set("steve", "bye");
		$config->save(false);
```
Output:
```yml
---
steve: hi
...
```
Expected output:
```yml
---
steve: bye
...
```

Additionally, if your configs are causing you performance issues when you're saving, it's a clear sign that
a) you're saving too much
b) you're abusing configs and should consider using a database.

Configs should be used for _simple_ data which does not change much. Configuration is such that the _user_ is expected to be able to modify it. As such, it should never be an issue to save synchronously.

In the future, something like ReactPHP may be introduced to allow proper async saving. When this happens, async saving would always be sequential but non blocking. Using threads for this makes no sense.
2018-07-12 19:31:00 +01:00
1d5c741f28 PluginBase: Automatically save default config if it doesn't exist (#2285)
I wasn't sure whether this would be considered a bug fix or a feature. Nonetheless, it's a behavioural change, so it belongs in 3.1 if anywhere.

Prior to this, plugins would be required to call saveDefaultConfig() before calling getConfig() or anything else. Calling getConfig() without saveDefaultConfig() first would generate an empty configuration file. Instead, it now saves the default config before loading it.
2018-07-12 19:25:48 +01:00
3a373b880d Listener: Add documentation on functionality (#2292)
The Listener interface is one of the most magical parts of PocketMine-MP, and before this pull request it didn't have a single bit of documentation.
2018-07-12 19:24:46 +01:00
1b7cd156aa Merge branch 'release/3.0' into release/3.1 2018-07-12 18:04:19 +01:00
7a164a8254 PluginManager: Allow @ignoreCancelled annotation on event handlers to not have parameters (#2294) 2018-07-12 17:12:14 +01:00
4a5ff32d2e hacks for NPC and floating text
I didn't think mojang could break this fucking game any worse
2018-07-11 19:45:48 +01:00
066c990301 Merge branch 'release/3.0' into release/3.1 2018-07-11 10:21:16 +01:00
b5dcdea6d8 Protocol changes for 1.5.0 "release"
what a piece of shit this version is...
2018-07-11 10:00:15 +01:00
287ff8d7bf Merge branch 'release/3.0' into release/3.1 2018-07-11 09:15:19 +01:00
1087212d75 Merge branch 'release/3.0' into release/3.1 2018-07-10 12:48:02 +01:00
0c350f2f57 Add quitMessage parameter to Player::kick() 2018-07-09 18:40:30 +01:00
bfcef2ab6b Add setReason() method to PlayerKickEvent 2018-07-09 18:36:19 +01:00
2994d0f3ae Merge branch 'release/3.0' into release/3.1 2018-07-09 10:06:28 +01:00
57cc0ebe75 Merge branch 'release/3.0' into release/3.1 2018-07-08 12:17:06 +01:00
7554d9a370 Empty merge 2018-07-07 19:22:30 +01:00
32574118ea Implemented Mending enchantment (#2257) 2018-07-06 13:28:33 +01:00
5a3135659b Merge branch 'release/3.0' into release/3.1 2018-07-06 13:12:13 +01:00
b90d7d1839 Merge branch 'release/3.0' into release/3.1 2018-07-05 17:43:11 +01:00
670b940837 PocketMine.php: clean up on platform dependency checks 2018-07-05 17:32:13 +01:00
6cad7be3ef Merge branch 'release/3.0' into release/3.1 2018-07-05 12:11:12 +01:00
28a72a93b4 Chunk: Use an SplFixedArray for heightmap
this goes on 3.1 because it changes the behaviour of chunk cloning, which might possibly break some plugins, and this isn't a bug fix.

This should see no change in behaviour other than a minor performance improvement and slight reduction in memory usage.
2018-07-05 11:58:20 +01:00
0f0d12bebc Merge branch 'release/3.0' into release/3.1 2018-07-02 16:58:15 +01:00
dfc11abf2d Level: fixed sendBlocks() documentation 2018-07-02 16:53:48 +01:00
17eef9f902 Level: stricten type checks on sendBlocks()
because people are morons
2018-07-02 16:53:00 +01:00
b04319a4ab Merge branch 'release/3.0' into release/3.1 2018-06-29 12:30:52 +01:00
0afbf6c547 Merge branch 'release/3.0' into release/3.1 2018-06-29 12:19:25 +01:00
ec2cca04a7 Merge branch 'release/3.0' into release/3.1 2018-06-24 17:34:37 +01:00
272b76d24c fix Punch mess 2018-06-24 13:43:52 +01:00
8c672cb7c8 Implemented Sharpness, Fire Aspect and Knockback enchantments 2018-06-24 12:13:54 +01:00
4d9368f205 Merge branch 'release/3.0' into release/3.1 2018-06-24 12:07:45 +01:00
97c267c70c Implemented Punch enchantment 2018-06-23 17:40:01 +01:00
85a3c0e7dc Implemented Flame enchantment 2018-06-23 17:11:20 +01:00
2f70a1eefb Implemented Thorns enchantment (#2258)
This implementation is rough and can probably be improved to make it extendable, but this works for now and can be improved later.
2018-06-23 13:36:58 +01:00
7ba6e92b6c Merge branch 'release/3.0' into release/3.1 2018-06-23 13:04:05 +01:00
47c862bc38 Projectile: check for blockhit change on nearby blockupdate 2018-06-23 12:57:13 +01:00
860c20109b TNT can now be ignited by burning arrows 2018-06-23 12:54:21 +01:00
1c0b49343c Implemented Infinity enchantment (#2259) 2018-06-23 11:44:35 +01:00
814a949580 Implemented Power enchantment 2018-06-23 11:39:39 +01:00
b393f5f17e Projectile: ensure that damage multiplier gets saved and restored 2018-06-23 10:41:04 +01:00
f1970492c1 Projectile: added API to modify projectile base damage multiplier
This adds two new methods:
- Projectile->getBaseDamage()
- Projectile->setBaseDamage()
2018-06-23 10:38:58 +01:00
4c9ca53b32 Merge branch 'release/3.0' into release/3.1 2018-06-22 17:47:33 +01:00
390db976e5 Arrow: allow controlling pickup mode (like PC)
This allows controlling how arrows are picked up:
- by anything
- by only creative players
- by nothing

This adds new API methods to Arrow:
- getPickupMode()
- setPickupMode()

This adds new public constants to Arrow:
- PICKUP_NONE
- PICKUP_ANY
- PICKUP_CREATIVE
2018-06-22 13:40:32 +01:00
98ac534820 bump version 2018-06-22 13:22:11 +01:00
392 changed files with 7879 additions and 2673 deletions

3
.gitmodules vendored
View File

@ -7,9 +7,6 @@
[submodule "tests/plugins/PocketMine-DevTools"]
path = tests/plugins/PocketMine-DevTools
url = https://github.com/pmmp/PocketMine-DevTools.git
[submodule "tests/plugins/PocketMine-TesterPlugin"]
path = tests/plugins/PocketMine-TesterPlugin
url = https://github.com/pmmp/PocketMine-TesterPlugin.git
[submodule "src/pocketmine/resources/vanilla"]
path = src/pocketmine/resources/vanilla
url = https://github.com/pmmp/BedrockData.git

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.1",
"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": {

164
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": "d3fb809caf4d5a5c99054f47f28ff271",
"packages": [
{
"name": "pocketmine/binaryutils",
"version": "0.1.0",
"name": "adhocore/json-comment",
"version": "v0.0.7",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BinaryUtils.git",
"reference": "c824ac67eeeb6899c2a9ec91a769eb9ed6e3f595"
"url": "https://github.com/adhocore/php-json-comment.git",
"reference": "135356c7e7336ef59924f1d921c770045f937a76"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/c824ac67eeeb6899c2a9ec91a769eb9ed6e3f595",
"reference": "c824ac67eeeb6899c2a9ec91a769eb9ed6e3f595",
"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.5",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BinaryUtils.git",
"reference": "03361b0d78ef2b400a99e96406aa594a5bc1c4ed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BinaryUtils/zipball/03361b0d78ef2b400a99e96406aa594a5bc1c4ed",
"reference": "03361b0d78ef2b400a99e96406aa594a5bc1c4ed",
"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.5",
"issues": "https://github.com/pmmp/BinaryUtils/issues"
},
"time": "2018-04-16T09:05:08+00:00"
"time": "2019-01-04T13:32:11+00:00"
},
{
"name": "pocketmine/math",
"version": "0.2.0",
"version": "0.2.2",
"source": {
"type": "git",
"url": "https://github.com/pmmp/Math.git",
"reference": "95ae5600328ed2add44c0bc830a68d3660e9e0ef"
"reference": "b755d3fb7025c4ddb7d9d6df0ba7e0b65125e51c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/Math/zipball/95ae5600328ed2add44c0bc830a68d3660e9e0ef",
"reference": "95ae5600328ed2add44c0bc830a68d3660e9e0ef",
"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/master",
"source": "https://github.com/pmmp/Math/tree/0.2.2",
"issues": "https://github.com/pmmp/Math/issues"
},
"time": "2018-06-09T09:26:30+00:00"
"time": "2019-01-04T15:42:36+00:00"
},
{
"name": "pocketmine/nbt",
"version": "0.2.0",
"version": "0.2.4",
"source": {
"type": "git",
"url": "https://github.com/pmmp/NBT.git",
"reference": "da19487ff92f6f7a16b5ce8894132bb1d1e9ea0c"
"reference": "05dddb51830fd8f3b6c93e553abe07643ec96fc5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/da19487ff92f6f7a16b5ce8894132bb1d1e9ea0c",
"reference": "da19487ff92f6f7a16b5ce8894132bb1d1e9ea0c",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/05dddb51830fd8f3b6c93e553abe07643ec96fc5",
"reference": "05dddb51830fd8f3b6c93e553abe07643ec96fc5",
"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.4",
"issues": "https://github.com/pmmp/NBT/issues"
},
"time": "2018-06-13T09:56:00+00:00"
"time": "2019-01-04T15:28:44+00:00"
},
{
"name": "pocketmine/raklib",
"version": "0.12.0",
"version": "0.12.1",
"source": {
"type": "git",
"url": "https://github.com/pmmp/RakLib.git",
"reference": "922da28efd828e2af6c19db1676ea9b6a267071c"
"reference": "334b469f2d0f070f17902d7ac584bea7c6149dc6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/922da28efd828e2af6c19db1676ea9b6a267071c",
"reference": "922da28efd828e2af6c19db1676ea9b6a267071c",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/334b469f2d0f070f17902d7ac584bea7c6149dc6",
"reference": "334b469f2d0f070f17902d7ac584bea7c6149dc6",
"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.1",
"issues": "https://github.com/pmmp/RakLib/issues"
},
"time": "2018-06-13T10:06:14+00:00"
"time": "2019-01-04T14:23:37+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",
@ -219,14 +304,15 @@
"support": {
"source": "https://github.com/pmmp/SPL/tree/master"
},
"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

@ -30,9 +30,69 @@ 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 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 +114,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();
@ -150,7 +211,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",
@ -188,54 +249,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){
@ -243,6 +276,9 @@ class MemoryManager{
if($this->garbageCollectionAsync){
$pool = $this->server->getAsyncPool();
if(($w = $pool->shutdownUnusedWorkers()) > 0){
$this->server->getLogger()->debug("Shut down $w idle async pool workers");
}
foreach($pool->getRunningWorkers() as $i){
$pool->submitTaskToWorker(new GarbageCollectionTask(), $i);
}
@ -470,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->getName()) . ".dat")){
if($this->server->hasOfflinePlayerData($this->name)){
$this->namedtag = $this->server->getOfflinePlayerData($this->name);
}else{
$this->namedtag = null;
}
}
@ -64,7 +62,7 @@ class OfflinePlayer implements IPlayer, Metadatable{
}
public function isOp() : bool{
return $this->server->isOp(strtolower($this->getName()));
return $this->server->isOp($this->name);
}
public function setOp(bool $value){
@ -73,38 +71,38 @@ class OfflinePlayer implements IPlayer, Metadatable{
}
if($value){
$this->server->addOp(strtolower($this->getName()));
$this->server->addOp($this->name);
}else{
$this->server->removeOp(strtolower($this->getName()));
$this->server->removeOp($this->name);
}
}
public function isBanned() : bool{
return $this->server->getNameBans()->isBanned(strtolower($this->getName()));
return $this->server->getNameBans()->isBanned($this->name);
}
public function setBanned(bool $value){
if($value){
$this->server->getNameBans()->addBan($this->getName(), null, null, null);
$this->server->getNameBans()->addBan($this->name, null, null, null);
}else{
$this->server->getNameBans()->remove($this->getName());
$this->server->getNameBans()->remove($this->name);
}
}
public function isWhitelisted() : bool{
return $this->server->isWhitelisted(strtolower($this->getName()));
return $this->server->isWhitelisted($this->name);
}
public function setWhitelisted(bool $value){
if($value){
$this->server->addWhitelist(strtolower($this->getName()));
$this->server->addWhitelist($this->name);
}else{
$this->server->removeWhitelist(strtolower($this->getName()));
$this->server->removeWhitelist($this->name);
}
}
public function getPlayer(){
return $this->server->getPlayerExact($this->getName());
return $this->server->getPlayerExact($this->name);
}
public function getFirstPlayed(){

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.0.8";
const BASE_VERSION = "3.5.5";
const IS_DEVELOPMENT_BUILD = false;
const BUILD_NUMBER = 0;
@ -53,83 +53,89 @@ namespace pocketmine {
* Enjoy it as much as I did writing it. I don't want to do it again.
*/
if(version_compare(MIN_PHP_VERSION, PHP_VERSION) > 0){
critical_error(\pocketmine\NAME . " requires PHP >= " . MIN_PHP_VERSION . ", but you have PHP " . PHP_VERSION . ".");
critical_error("Please refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
exit(1);
}
if(PHP_INT_SIZE < 8){
critical_error("Running " . \pocketmine\NAME . " with 32-bit systems/PHP is no longer supported.");
critical_error("Please upgrade to a 64-bit system, or use a 64-bit PHP binary if this is a 64-bit system.");
critical_error("Please refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
exit(1);
}
/* Dependencies check */
$errors = 0;
if(php_sapi_name() !== "cli"){
critical_error("You must run " . \pocketmine\NAME . " using the CLI.");
++$errors;
}
$extensions = [
"bcmath" => "BC Math",
"curl" => "cURL",
"ctype" => "ctype",
"date" => "Date",
"hash" => "Hash",
"json" => "JSON",
"mbstring" => "Multibyte String",
"openssl" => "OpenSSL",
"pcre" => "PCRE",
"phar" => "Phar",
"pthreads" => "pthreads",
"reflection" => "Reflection",
"sockets" => "Sockets",
"spl" => "SPL",
"yaml" => "YAML",
"zip" => "Zip",
"zlib" => "Zlib"
];
foreach($extensions as $ext => $name){
if(!extension_loaded($ext)){
critical_error("Unable to find the $name ($ext) extension.");
++$errors;
/**
* @return string[]
*/
function check_platform_dependencies(){
if(version_compare(MIN_PHP_VERSION, PHP_VERSION) > 0){
//If PHP version isn't high enough, anything below might break, so don't bother checking it.
return [
\pocketmine\NAME . " requires PHP >= " . MIN_PHP_VERSION . ", but you have PHP " . PHP_VERSION . "."
];
}
}
if(extension_loaded("pthreads")){
$pthreads_version = phpversion("pthreads");
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
$messages = [];
if(PHP_INT_SIZE < 8){
$messages[] = "Running " . \pocketmine\NAME . " with 32-bit systems/PHP is no longer supported. Please upgrade to a 64-bit system, or use a 64-bit PHP binary if this is a 64-bit system.";
}
if(version_compare($pthreads_version, "3.1.7dev") < 0){
critical_error("pthreads >= 3.1.7dev is required, while you have $pthreads_version.");
++$errors;
if(php_sapi_name() !== "cli"){
$messages[] = "You must run " . \pocketmine\NAME . " using the CLI.";
}
}
if(extension_loaded("leveldb")){
$leveldb_version = phpversion("leveldb");
if(version_compare($leveldb_version, "0.2.1") < 0){
critical_error("php-leveldb >= 0.2.1 is required, while you have $leveldb_version");
++$errors;
$extensions = [
"bcmath" => "BC Math",
"curl" => "cURL",
"ctype" => "ctype",
"date" => "Date",
"hash" => "Hash",
"json" => "JSON",
"mbstring" => "Multibyte String",
"openssl" => "OpenSSL",
"pcre" => "PCRE",
"phar" => "Phar",
"pthreads" => "pthreads",
"reflection" => "Reflection",
"sockets" => "Sockets",
"spl" => "SPL",
"yaml" => "YAML",
"zip" => "Zip",
"zlib" => "Zlib"
];
foreach($extensions as $ext => $name){
if(!extension_loaded($ext)){
$messages[] = "Unable to find the $name ($ext) extension.";
}
}
if(extension_loaded("pthreads")){
$pthreads_version = phpversion("pthreads");
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
if(version_compare($pthreads_version, "3.1.7dev") < 0){
$messages[] = "pthreads >= 3.1.7dev is required, while you have $pthreads_version.";
}
}
if(extension_loaded("leveldb")){
$leveldb_version = phpversion("leveldb");
if(version_compare($leveldb_version, "0.2.1") < 0){
$messages[] = "php-leveldb >= 0.2.1 is required, while you have $leveldb_version.";
}
}
if(extension_loaded("pocketmine")){
$messages[] = "The native PocketMine extension is no longer supported.";
}
return $messages;
}
if(extension_loaded("pocketmine")){
critical_error("The native PocketMine extension is no longer supported.");
++$errors;
}
if($errors > 0){
if(!empty($messages = check_platform_dependencies())){
echo PHP_EOL;
$binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown";
critical_error("Selected PHP binary ($binary) does not satisfy some requirements.");
foreach($messages as $m){
echo " - $m" . PHP_EOL;
}
critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
echo PHP_EOL;
exit(1);
}
unset($messages);
error_reporting(-1);
@ -139,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);
}

View File

@ -39,6 +39,7 @@ use pocketmine\event\HandlerList;
use pocketmine\event\level\LevelInitEvent;
use pocketmine\event\level\LevelLoadEvent;
use pocketmine\event\player\PlayerDataSaveEvent;
use pocketmine\event\server\CommandEvent;
use pocketmine\event\server\QueryRegenerateEvent;
use pocketmine\event\server\ServerCommandEvent;
use pocketmine\inventory\CraftingManager;
@ -82,6 +83,7 @@ use pocketmine\network\rcon\RCON;
use pocketmine\network\upnp\UPnP;
use pocketmine\permission\BanList;
use pocketmine\permission\DefaultPermissions;
use pocketmine\permission\PermissionManager;
use pocketmine\plugin\PharPluginLoader;
use pocketmine\plugin\Plugin;
use pocketmine\plugin\PluginLoadOrder;
@ -89,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;
@ -97,13 +98,84 @@ 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;
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 gc_collect_cycles;
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
@ -195,9 +267,6 @@ class Server{
/** @var ResourcePackManager */
private $resourceManager;
/** @var ConsoleCommandSender */
private $consoleSender;
/** @var int */
private $maxPlayers;
@ -553,10 +622,11 @@ class Server{
}
/**
* @deprecated
* @return bool
*/
public function getAllowFlight() : bool{
return $this->getConfigBool("allow-flight", false);
return true;
}
/**
@ -731,6 +801,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
*
@ -802,22 +883,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);
@ -988,6 +1064,7 @@ class Server{
/**
* @internal
*
* @param Level $level
*/
public function removeLevel(Level $level) : void{
@ -1025,18 +1102,12 @@ class Server{
return false;
}
try{
$level = new Level($this, $name, new $providerClass($path));
}catch(\Throwable $e){
$this->logger->error($this->getLanguage()->translateString("pocketmine.level.loadError", [$name, $e->getMessage()]));
$this->logger->logException($e);
return false;
}
/** @see LevelProvider::__construct() */
$level = new Level($this, $name, new $providerClass($path));
$this->levels[$level->getId()] = $level;
$this->getPluginManager()->callEvent(new LevelLoadEvent($level));
(new LevelLoadEvent($level))->call();
$level->setTickRate($this->baseTickRate);
@ -1058,7 +1129,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", "");
@ -1075,24 +1146,19 @@ class Server{
}
}
try{
$path = $this->getDataPath() . "worlds/" . $name . "/";
/** @var LevelProvider $providerClass */
$providerClass::generate($path, $name, $seed, $generator, $options);
$path = $this->getDataPath() . "worlds/" . $name . "/";
/** @var LevelProvider $providerClass */
$providerClass::generate($path, $name, $seed, $generator, $options);
$level = new Level($this, $name, new $providerClass($path));
$this->levels[$level->getId()] = $level;
/** @see LevelProvider::__construct() */
$level = new Level($this, $name, new $providerClass($path));
$this->levels[$level->getId()] = $level;
$level->setTickRate($this->baseTickRate);
}catch(\Throwable $e){
$this->logger->error($this->getLanguage()->translateString("pocketmine.level.generationError", [$name, $e->getMessage()]));
$this->logger->logException($e);
return false;
}
$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]));
@ -1146,17 +1212,12 @@ class Server{
* Useful for tracking entities across multiple worlds without needing strong references.
*
* @param int $entityId
* @param Level|null $expectedLevel Level to look in first for the target
* @param Level|null $expectedLevel @deprecated Level to look in first for the target
*
* @return Entity|null
*/
public function findEntity(int $entityId, Level $expectedLevel = null){
$levels = $this->levels;
if($expectedLevel !== null){
array_unshift($levels, $expectedLevel);
}
foreach($levels as $level){
foreach($this->levels as $level){
assert(!$level->isClosed());
if(($entity = $level->getEntity($entityId)) instanceof Entity){
return $entity;
@ -1303,7 +1364,7 @@ class Server{
if(($player = $this->getPlayerExact($name)) !== null){
$player->recalculatePermissions();
}
$this->operators->save(true);
$this->operators->save();
}
/**
@ -1323,7 +1384,7 @@ class Server{
*/
public function addWhitelist(string $name){
$this->whitelist->set(strtolower($name), true);
$this->whitelist->save(true);
$this->whitelist->save();
}
/**
@ -1450,31 +1511,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",
@ -1483,9 +1519,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,
@ -1500,9 +1533,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]));
@ -1540,10 +1600,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);
@ -1619,7 +1691,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();
@ -1636,7 +1707,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);
$this->pluginManager->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());
@ -1694,7 +1764,7 @@ class Server{
}
if($this->properties->hasChanged()){
$this->properties->save(true);
$this->properties->save();
}
if(!($this->getDefaultLevel() instanceof Level)){
@ -1745,7 +1815,7 @@ class Server{
if(!is_array($recipients)){
/** @var Player[] $recipients */
$recipients = [];
foreach($this->pluginManager->getPermissionSubscriptions(self::BROADCAST_CHANNEL_USERS) as $permissible){
foreach(PermissionManager::getInstance()->getPermissionSubscriptions(self::BROADCAST_CHANNEL_USERS) as $permissible){
if($permissible instanceof Player and $permissible->hasPermission(self::BROADCAST_CHANNEL_USERS)){
$recipients[spl_object_hash($permissible)] = $permissible; // do not send messages directly, or some might be repeated
}
@ -1771,7 +1841,7 @@ class Server{
/** @var Player[] $recipients */
$recipients = [];
foreach($this->pluginManager->getPermissionSubscriptions(self::BROADCAST_CHANNEL_USERS) as $permissible){
foreach(PermissionManager::getInstance()->getPermissionSubscriptions(self::BROADCAST_CHANNEL_USERS) as $permissible){
if($permissible instanceof Player and $permissible->hasPermission(self::BROADCAST_CHANNEL_USERS)){
$recipients[spl_object_hash($permissible)] = $permissible; // do not send messages directly, or some might be repeated
}
@ -1801,7 +1871,7 @@ class Server{
/** @var Player[] $recipients */
$recipients = [];
foreach($this->pluginManager->getPermissionSubscriptions(self::BROADCAST_CHANNEL_USERS) as $permissible){
foreach(PermissionManager::getInstance()->getPermissionSubscriptions(self::BROADCAST_CHANNEL_USERS) as $permissible){
if($permissible instanceof Player and $permissible->hasPermission(self::BROADCAST_CHANNEL_USERS)){
$recipients[spl_object_hash($permissible)] = $permissible; // do not send messages directly, or some might be repeated
}
@ -1826,7 +1896,7 @@ class Server{
/** @var CommandSender[] $recipients */
$recipients = [];
foreach(explode(";", $permissions) as $permission){
foreach($this->pluginManager->getPermissionSubscriptions($permission) as $permissible){
foreach(PermissionManager::getInstance()->getPermissionSubscriptions($permission) as $permissible){
if($permissible instanceof CommandSender and $permissible->hasPermission($permission)){
$recipients[spl_object_hash($permissible)] = $permissible; // do not send messages directly, or some might be repeated
}
@ -1935,26 +2005,26 @@ 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
*
* @param CommandSender $sender
* @param string $commandLine
* @param bool $internal
*
* @return bool
*/
public function dispatchCommand(CommandSender $sender, string $commandLine) : bool{
public function dispatchCommand(CommandSender $sender, string $commandLine, bool $internal = false) : bool{
if(!$internal){
$ev = new CommandEvent($sender, $commandLine);
$ev->call();
if($ev->isCancelled()){
return false;
}
$commandLine = $ev->getCommand();
}
if($this->commandMap->dispatch($sender, $commandLine)){
return true;
}
@ -1974,6 +2044,7 @@ class Server{
$this->pluginManager->disablePlugins();
$this->pluginManager->clearPlugins();
PermissionManager::getInstance()->clearPermissions();
$this->commandMap->clearCommands();
$this->logger->info("Reloading properties...");
@ -2013,6 +2084,10 @@ class Server{
return;
}
if($this->doTitleTick){
echo "\x1b]0;\x07";
}
try{
if(!$this->isRunning()){
$this->sendUsage(SendUsageTask::TYPE_CLOSE);
@ -2144,10 +2219,6 @@ class Server{
* @param array|null $trace
*/
public function exceptionHandler(\Throwable $e, $trace = null){
if($e === null){
return;
}
global $lastError;
if($trace === null){
@ -2170,7 +2241,7 @@ class Server{
"fullFile" => $e->getFile(),
"file" => $errfile,
"line" => $errline,
"trace" => Utils::getTrace(0, $trace)
"trace" => $trace
];
global $lastExceptionError, $lastError;
@ -2197,15 +2268,23 @@ 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");
}
}
if($dump->getData()["error"]["type"] === "E_PARSE" or $dump->getData()["error"]["type"] === "E_COMPILE_ERROR"){
if($dump->getData()["error"]["type"] === \ParseError::class){
$report = false;
}
@ -2216,7 +2295,7 @@ class Server{
if($report){
$url = ($this->getProperty("auto-report.use-https", true) ? "https" : "http") . "://" . $this->getProperty("auto-report.host", "crash.pmmp.io") . "/submit/api";
$reply = Utils::postURL($url, [
$reply = Internet::postURL($url, [
"report" => "yes",
"name" => $this->getName() . " " . $this->getPocketMineVersion(),
"email" => "crash@pocketmine.net",
@ -2239,6 +2318,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);
}
@ -2311,7 +2397,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);
}
@ -2334,7 +2420,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);
@ -2350,41 +2436,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);
}
}
}
@ -2394,7 +2476,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);
}
@ -2478,9 +2560,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);
}
@ -2531,13 +2611,9 @@ class Server{
}
if(($this->tickCounter & 0b111111111) === 0){
try{
$this->getPluginManager()->callEvent($this->queryRegenerateTask = new QueryRegenerateEvent($this, 5));
if($this->queryHandler !== null){
$this->queryHandler->regenerateInfo();
}
}catch(\Throwable $e){
$this->logger->logException($e);
($this->queryRegenerateTask = new QueryRegenerateEvent($this, 5))->call();
if($this->queryHandler !== null){
$this->queryHandler->regenerateInfo();
}
}
@ -2575,10 +2651,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

@ -67,14 +67,10 @@ abstract class Thread extends \Thread{
public function start(?int $options = \PTHREADS_INHERIT_ALL){
ThreadManager::getInstance()->add($this);
if(!$this->isRunning() and !$this->isJoined() and !$this->isTerminated()){
if($this->getClassLoader() === null){
$this->setClassLoader();
}
return parent::start($options);
if($this->getClassLoader() === null){
$this->setClassLoader();
}
return false;
return parent::start($options);
}
/**
@ -83,12 +79,9 @@ abstract class Thread extends \Thread{
public function quit(){
$this->isKilled = true;
$this->notify();
if(!$this->isJoined()){
if(!$this->isTerminated()){
$this->join();
}
$this->notify();
$this->join();
}
ThreadManager::getInstance()->remove($this);

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

@ -67,14 +67,10 @@ abstract class Worker extends \Worker{
public function start(?int $options = \PTHREADS_INHERIT_ALL){
ThreadManager::getInstance()->add($this);
if(!$this->isRunning() and !$this->isJoined() and !$this->isTerminated()){
if($this->getClassLoader() === null){
$this->setClassLoader();
}
return parent::start($options);
if($this->getClassLoader() === null){
$this->setClassLoader();
}
return false;
return parent::start($options);
}
/**
@ -83,16 +79,10 @@ abstract class Worker extends \Worker{
public function quit(){
$this->isKilled = true;
$this->notify();
if($this->isRunning()){
$this->shutdown();
while($this->unstack() !== null);
$this->notify();
$this->unstack();
}elseif(!$this->isJoined()){
if(!$this->isTerminated()){
$this->join();
}
$this->shutdown();
}
ThreadManager::getInstance()->remove($this);

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,8 @@ use pocketmine\metadata\Metadatable;
use pocketmine\metadata\MetadataValue;
use pocketmine\Player;
use pocketmine\plugin\Plugin;
use function array_merge;
use const PHP_INT_MAX;
class Block extends Position implements BlockIds, Metadatable{
@ -109,6 +111,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
*/

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
@ -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,8 @@ class BlockFactory{
public static function registerStaticRuntimeIdMappings() : void{
/** @var mixed[] $runtimeIdMap */
$runtimeIdMap = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "runtimeid_table.json"), true);
foreach($runtimeIdMap as $obj){
self::registerMapping($obj["runtimeID"], $obj["id"], $obj["data"]);
foreach($runtimeIdMap as $k => $obj){
self::registerMapping($k, $obj["id"], $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{
@ -77,7 +76,7 @@ class Cactus extends Transparent{
}else{
for($side = 2; $side <= 5; ++$side){
$b = $this->getSide($side);
if(!$b->canBeFlowedInto()){
if($b->isSolid()){
$this->getLevel()->useBreakOn($this);
break;
}
@ -95,7 +94,8 @@ 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)));
$ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS));
$ev->call();
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
}
@ -117,7 +117,7 @@ class Cactus extends Transparent{
$block1 = $this->getSide(Vector3::SIDE_SOUTH);
$block2 = $this->getSide(Vector3::SIDE_WEST);
$block3 = $this->getSide(Vector3::SIDE_EAST);
if($block0->isTransparent() and $block1->isTransparent() and $block2->isTransparent() and $block3->isTransparent()){
if(!$block0->isSolid() and !$block1->isSolid() and !$block2->isSolid() and !$block3->isSolid()){
$this->getLevel()->setBlock($this, $this, true);
return true;

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{
@ -57,7 +58,7 @@ class CoalOre extends Solid{
];
}
public function getXpDropForTool(Item $item) : int{
protected function getXpDropAmount() : int{
return mt_rand(0, 2);
}
}

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{
@ -50,8 +50,8 @@ abstract class Crops extends Flowable{
$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

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

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

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

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

@ -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,7 +48,8 @@ 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)));
$ev = new BlockGrowEvent($b, BlockFactory::get(Block::SUGARCANE_BLOCK));
$ev->call();
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
}

View File

@ -24,11 +24,15 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Arrow;
use pocketmine\item\FlintSteel;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\utils\Random;
use function cos;
use function sin;
use const M_PI;
class TNT extends Solid{
@ -56,6 +60,16 @@ class TNT extends Solid{
return false;
}
public function hasEntityCollision() : bool{
return true;
}
public function onEntityCollide(Entity $entity) : void{
if($entity instanceof Arrow and $entity->isOnFire()){
$this->ignite();
}
}
public function ignite(int $fuse = 80){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), 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 TallGrass extends Flowable{

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

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

@ -28,9 +28,12 @@ namespace pocketmine\command;
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{
@ -293,7 +296,7 @@ abstract class Command{
$m = clone $message;
$result = "[" . $source->getName() . ": " . ($source->getServer()->getLanguage()->get($m->getText()) !== $m->getText() ? "%" : "") . $m->getText() . "]";
$users = $source->getServer()->getPluginManager()->getPermissionSubscriptions(Server::BROADCAST_CHANNEL_ADMINISTRATIVE);
$users = PermissionManager::getInstance()->getPermissionSubscriptions(Server::BROADCAST_CHANNEL_ADMINISTRATIVE);
$colored = TextFormat::GRAY . TextFormat::ITALIC . $result;
$m->setText($result);
@ -301,7 +304,7 @@ abstract class Command{
$m->setText($colored);
$colored = clone $m;
}else{
$users = $source->getServer()->getPluginManager()->getPermissionSubscriptions(Server::BROADCAST_CHANNEL_ADMINISTRATIVE);
$users = PermissionManager::getInstance()->getPermissionSubscriptions(Server::BROADCAST_CHANNEL_ADMINISTRATIVE);
$result = new TranslationContainer("chat.type.admin", [$source->getName(), $message]);
$colored = new TranslationContainer(TextFormat::GRAY . TextFormat::ITALIC . "%chat.type.admin", [$source->getName(), $message]);
}

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,17 +53,12 @@ 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;
}
}
foreach($commands as $command){
$result |= Server::getInstance()->dispatchCommand($sender, $command);
$result |= Server::getInstance()->dispatchCommand($sender, $command, true);
}
return (bool) $result;

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_map;
use function array_shift;
use function count;
use function explode;
use function implode;
use function min;
use function str_getcsv;
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,7 @@ class SimpleCommandMap implements CommandMap{
}
public function dispatch(CommandSender $sender, string $commandLine) : bool{
$args = array_map("stripslashes", str_getcsv($commandLine, " "));
$args = array_map("\stripslashes", str_getcsv($commandLine, " "));
$sentCommandLabel = "";
$target = $this->matchCommand($sentCommandLabel, $args);
@ -258,14 +261,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;
}
@ -302,9 +301,9 @@ class SimpleCommandMap implements CommandMap{
}
$targets = [];
$bad = [];
$recursive = [];
$bad = "";
$recursive = "";
foreach($commandStrings as $commandString){
$args = explode(" ", $commandString);
$commandName = "";
@ -312,27 +311,21 @@ class SimpleCommandMap implements CommandMap{
if($command === null){
if(strlen($bad) > 0){
$bad .= ", ";
}
$bad .= $commandString;
$bad[] = $commandString;
}elseif($commandName === $alias){
if($recursive !== ""){
$recursive .= ", ";
}
$recursive .= $commandString;
$recursive[] = $commandString;
}else{
$targets[] = $commandString;
}
}
if($recursive !== ""){
$this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.command.alias.recursive", [$alias, $recursive]));
if(!empty($recursive)){
$this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.command.alias.recursive", [$alias, implode(", ", $recursive)]));
continue;
}
if(strlen($bad) > 0){
$this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.command.alias.notFound", [$alias, $bad]));
if(!empty($bad)){
$this->server->getLogger()->warning($this->server->getLanguage()->translateString("pocketmine.command.alias.notFound", [$alias, implode(", ", $bad)]));
continue;
}

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{

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{

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{

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{
@ -62,15 +63,7 @@ class KillCommand extends VanillaCommand{
$player = $sender->getServer()->getPlayer($args[0]);
if($player instanceof Player){
$sender->getServer()->getPluginManager()->callEvent($ev = new EntityDamageEvent($player, EntityDamageEvent::CAUSE_SUICIDE, 1000));
if($ev->isCancelled()){
return true;
}
$player->setLastDamageCause($ev);
$player->setHealth(0);
$player->attack(new EntityDamageEvent($player, EntityDamageEvent::CAUSE_SUICIDE, 1000));
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.kill.successful", [$player->getName()]));
}else{
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.player.notFound"));
@ -86,14 +79,7 @@ class KillCommand extends VanillaCommand{
return true;
}
$sender->getServer()->getPluginManager()->callEvent($ev = new EntityDamageEvent($sender, EntityDamageEvent::CAUSE_SUICIDE, 1000));
if($ev->isCancelled()){
return true;
}
$sender->setLastDamageCause($ev);
$sender->setHealth(0);
$sender->attack(new EntityDamageEvent($sender, EntityDamageEvent::CAUSE_SUICIDE, 1000));
$sender->sendMessage(new TranslationContainer("commands.kill.successful", [$sender->getName()]));
}else{
throw new InvalidCommandSyntaxException();

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{

View File

@ -28,6 +28,8 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\lang\TranslationContainer;
use pocketmine\Player;
use pocketmine\utils\TextFormat;
use function count;
use function implode;
class MeCommand extends VanillaCommand{

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 OpCommand extends VanillaCommand{

View File

@ -27,6 +27,7 @@ use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\lang\TranslationContainer;
use function count;
class PardonCommand extends VanillaCommand{
@ -34,7 +35,8 @@ class PardonCommand extends VanillaCommand{
parent::__construct(
$name,
"%pocketmine.command.unban.player.description",
"%commands.unban.usage"
"%commands.unban.usage",
["unban"]
);
$this->setPermission("pocketmine.command.unban.player");
}

View File

@ -27,6 +27,8 @@ use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\lang\TranslationContainer;
use function count;
use function preg_match;
class PardonIpCommand extends VanillaCommand{
@ -34,7 +36,8 @@ class PardonIpCommand extends VanillaCommand{
parent::__construct(
$name,
"%pocketmine.command.unban.ip.description",
"%commands.unbanip.usage"
"%commands.unbanip.usage",
["unban-ip"]
);
$this->setPermission("pocketmine.command.unban.ip");
}

View File

@ -29,6 +29,7 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\lang\TranslationContainer;
use pocketmine\level\Level;
use pocketmine\level\particle\AngryVillagerParticle;
use pocketmine\level\particle\BlockForceFieldParticle;
use pocketmine\level\particle\BubbleParticle;
@ -61,6 +62,13 @@ use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\utils\Random;
use pocketmine\utils\TextFormat;
use function count;
use function explode;
use function max;
use function microtime;
use function mt_rand;
use function strpos;
use function strtolower;
class ParticleCommand extends VanillaCommand{
@ -84,14 +92,18 @@ class ParticleCommand extends VanillaCommand{
if($sender instanceof Player){
$level = $sender->getLevel();
$pos = new Vector3(
$this->getRelativeDouble($sender->getX(), $sender, $args[1]),
$this->getRelativeDouble($sender->getY(), $sender, $args[2], 0, Level::Y_MAX),
$this->getRelativeDouble($sender->getZ(), $sender, $args[3])
);
}else{
$level = $sender->getServer()->getDefaultLevel();
$pos = new Vector3((float) $args[1], (float) $args[2], (float) $args[3]);
}
$name = strtolower($args[0]);
$pos = new Vector3((float) $args[1], (float) $args[2], (float) $args[3]);
$xd = (float) $args[4];
$yd = (float) $args[5];
$zd = (float) $args[6];
@ -211,12 +223,12 @@ class ParticleCommand extends VanillaCommand{
}elseif(strpos($name, "blockcrack_") === 0){
$d = explode("_", $name);
if(count($d) === 2){
return new TerrainParticle($pos, BlockFactory::get($d[1] & 0xff, $d[1] >> 12));
return new TerrainParticle($pos, BlockFactory::get(((int) $d[1]) & 0xff, ((int) $d[1]) >> 12));
}
}elseif(strpos($name, "blockdust_") === 0){
$d = explode("_", $name);
if(count($d) >= 4){
return new DustParticle($pos, $d[1] & 0xff, $d[2] & 0xff, $d[3] & 0xff, isset($d[4]) ? $d[4] & 0xff : 255);
return new DustParticle($pos, ((int) $d[1]) & 0xff, ((int) $d[2]) & 0xff, ((int) $d[3]) & 0xff, isset($d[4]) ? ((int) $d[4]) & 0xff : 255);
}
}

View File

@ -25,7 +25,11 @@ namespace pocketmine\command\defaults;
use pocketmine\command\CommandSender;
use pocketmine\lang\TranslationContainer;
use pocketmine\plugin\Plugin;
use pocketmine\utils\TextFormat;
use function array_map;
use function count;
use function implode;
class PluginsCommand extends VanillaCommand{
@ -43,20 +47,12 @@ class PluginsCommand extends VanillaCommand{
if(!$this->testPermission($sender)){
return true;
}
$this->sendPluginList($sender);
$list = array_map(function(Plugin $plugin) : string{
return ($plugin->isEnabled() ? TextFormat::GREEN : TextFormat::RED) . $plugin->getDescription()->getFullName();
}, $sender->getServer()->getPluginManager()->getPlugins());
$sender->sendMessage(new TranslationContainer("pocketmine.command.plugins.success", [count($list), implode(TextFormat::WHITE . ", ", $list)]));
return true;
}
private function sendPluginList(CommandSender $sender){
$list = "";
foreach(($plugins = $sender->getServer()->getPluginManager()->getPlugins()) as $plugin){
if(strlen($list) > 0){
$list .= TextFormat::WHITE . ", ";
}
$list .= $plugin->isEnabled() ? TextFormat::GREEN : TextFormat::RED;
$list .= $plugin->getDescription()->getFullName();
}
$sender->sendMessage(new TranslationContainer("pocketmine.command.plugins.success", [count($plugins), $list]));
}
}

View File

@ -29,6 +29,8 @@ use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\lang\TranslationContainer;
use pocketmine\Player;
use pocketmine\utils\TextFormat;
use function count;
use function implode;
class SayCommand extends VanillaCommand{

View File

@ -30,6 +30,8 @@ use pocketmine\lang\TranslationContainer;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\utils\TextFormat;
use function count;
use function round;
class SetWorldSpawnCommand extends VanillaCommand{

View File

@ -31,6 +31,8 @@ use pocketmine\level\Level;
use pocketmine\level\Position;
use pocketmine\Player;
use pocketmine\utils\TextFormat;
use function count;
use function round;
class SpawnpointCommand extends VanillaCommand{

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