Compare commits

...

266 Commits

Author SHA1 Message Date
a1ce535d02 Remove the old plugin repo from README since it is dead/outdated 2017-06-23 23:21:34 +01:00
993af0fa30 Added build-denied action constant
don't need this, but good to have for completion's sake
2017-06-23 16:58:28 +01:00
b83c135c3f Made Item::setLore() fluent (#1120) 2017-06-23 08:39:56 +01:00
8bf1cc9e48 PHP version should be the very first thing to be checked 2017-06-23 01:52:53 +01:00
c70690a600 Fixed cleanPath() not working when the current working dir case doesn't match the actual path case 2017-06-22 19:49:27 +01:00
4b4f2af9e3 Fixed some very unusual crashdumps reporting non-fatal errors when plugins use die() or exit() 2017-06-22 19:08:33 +01:00
9047c2c1ef Updated DevTools submodule with /makeserver fix 2017-06-22 17:16:59 +01:00
89ca2ac2d5 Found an unknown field in ChangeDimensionPacket
No idea what this is actually used for though. It's set when a client dies in a different dimension and respawns in the overworld.
2017-06-22 15:52:29 +01:00
6a2a74a457 Improved git hash handling, add dirty git detection and disable automatic reporting for dirty builds 2017-06-22 13:35:04 +01:00
7ba807fd42 Update submodules 2017-06-22 09:41:07 +01:00
19410754c6 API bump 2017-06-22 09:34:04 +01:00
8cd31c2dc4 Fixed crashes starting RCON 2017-06-21 18:15:57 +01:00
c09a5ab301 Revert botched fix that broke teleports
Revert "Do chunk orders and sending during onUpdate() when we know the player has been constructed"

This reverts commit 080b35bf53.
2017-06-21 17:51:16 +01:00
a0ef15b15e New CrashArchive is up 2017-06-21 14:25:54 +01:00
03826d9cbc Fixed player spawnpoints glitching and not saving 2017-06-21 12:17:26 +01:00
080b35bf53 Do chunk orders and sending during onUpdate() when we know the player has been constructed 2017-06-21 11:54:05 +01:00
e9c46da7f0 Fixed glitching on respawn due to player 1.62 position offset 2017-06-21 11:27:50 +01:00
0f79b19fdc Removed masks for Y coordinates, fixed bugs related to out-of-bounds coordinates, fixed #914 (#915) 2017-06-21 10:55:38 +01:00
69ae37d191 Added no PvP flag for spectator mode, fixes nodamage sound in spectator 2017-06-21 09:42:26 +01:00
86742fcf30 Workaround for flight controls fail on teleport (TODO: fix this properly) 2017-06-20 20:10:20 +01:00
a4b8dd43e6 Removed useless confusing array indices in CompoundTag constructors (#1116) 2017-06-20 12:11:24 +01:00
e11f1e94e9 Cleaned up SubChunk implementation 2017-06-19 15:40:31 +01:00
938452bfe9 Clarified guidelines on useless issues 2017-06-19 13:43:10 +01:00
a724395148 Added exception handling to Player->close(), mitigates #1060 and #1101 2017-06-19 13:37:38 +01:00
bc10edfdd3 Removed incorrect use of \pocketmine\ANSI constant for debug logging in MainLogger constructor 2017-06-18 16:50:34 +01:00
f7d07ca155 Updated DevTools submodule 2017-06-18 11:46:31 +01:00
be7b057fa5 Improved metadata sending and made it less spammy
Add changed properties to a list to send in a group on tick in a single packet
2017-06-17 20:00:45 +01:00
8637e0224f Check protocol version before anything else 2017-06-17 19:30:37 +01:00
8919d4a372 Some refactoring to allow for light updates to be executed asynchronously 2017-06-17 17:38:47 +01:00
0cf3914f5d Player base offset doesn't change with scale, close #943, close #945 2017-06-17 12:59:41 +01:00
e9a638d84a Set a default value 0 for tick counter (#1108) 2017-06-17 12:42:42 +01:00
e3b3f60c66 Fixed item stack count and effect amplifier overflows, close #1072 2017-06-17 12:22:38 +01:00
1bae973502 Fix server crashing while crashing when trying to decode an invalid response from the crash-archive post 2017-06-17 10:31:20 +01:00
e0f8a02bb8 Catch and log all crashes occurring while creating crashdumps 2017-06-17 10:25:34 +01:00
846be84324 Fixed all file headers 2017-06-16 16:18:16 +01:00
8ef24423d1 This should never be null 2017-06-16 15:48:08 +01:00
8fc38c36f9 Fixed some derp Vector3 aliases 2017-06-16 13:48:53 +01:00
eb05f2ecde Added UpdateNotifyEvent 2017-06-15 11:16:13 +01:00
478e954b3f Updated preprocessor submodule 2017-06-15 11:04:52 +01:00
313fdb9e87 Added INT32_MIN and INT32_MAX constants and an exception throw for out-of-range effect amplifiers 2017-06-14 19:38:39 +01:00
1bf18ba8d2 Fixed messed-up header in ItemFrame 2017-06-14 18:46:35 +01:00
5011198a4e Cleaned up SetupWizard and fixed crash when pressing CTRL+C during setup 2017-06-13 17:38:19 +01:00
e96fa8b682 TODO: REVERT - Added a hack for InteractPacket spam issue 2017-06-12 19:50:31 +01:00
bf3868c078 Missed one 2017-06-12 09:33:48 +01:00
3167817e34 Fixed crash when memory hard limit is disabled, close #1074 2017-06-12 09:32:31 +01:00
433b8369f5 Point updater to new host update.pmmp.io 2017-06-11 19:15:35 +01:00
0612244b5e Fixed warn-ops config being useless 2017-06-11 19:07:41 +01:00
487233a101 Improved AutoUpdater error handling and made it more robust 2017-06-11 18:41:18 +01:00
4341fb8347 AddEntityPacket's attributes encoding is still non-standard -_-
I thought they fixed this...
2017-06-11 18:09:58 +01:00
789df942b6 Don't try to order packets sent with immediate priority, fixes #1026 2017-06-11 13:04:43 +01:00
9e99252817 Improved ListCommand and fixed crash when no players are online
I <3 closures
2017-06-11 10:56:16 +01:00
75cc2d6914 Cleaned up Utils::getIP(), resolved strict-type issues, close #1062 2017-06-11 10:25:48 +01:00
61b857a81c Fixed ExplodePacket
fixed-float my ass!
2017-06-10 19:54:04 +01:00
2024e9ecdf Fixed extremely stupid zero-length bug in BinaryStream
pls don't kill me 😢
2017-06-10 18:33:54 +01:00
4765242397 Drop support for 32 bit systems/PHP (#984)
* Cutting out 32-bit and minor improvements to bootstrap

* Byeeeeee

* Removing legacy code

* added note to the issue template
as suggested by @xxFlare
2017-06-10 16:11:28 +01:00
3687b149b9 Fix a couple of bugs exposed by php 7.2.0alpha1 2017-06-10 14:51:28 +01:00
1aae9e03b6 Fixed reference parameter fail in UpdateCheckTask, close #1048
not sure _why_ this doesn't work... maybe something to do with the old property being a member of a threaded object?
2017-06-09 19:51:18 +01:00
c43ab12a9a Fix spawnForced not specified in SetSpawnPositionPacket, close #1046 (#1047)
* Fix #1046

* Change spawnForced to false
2017-06-09 18:12:57 +01:00
cd66f58526 Restrict XpSeed to the bounds of an int32, close #1040 2017-06-09 16:05:28 +01:00
7870a8672e Remove useless duplicate check 2017-06-09 16:02:30 +01:00
eac756470a Fixed trying to save health as a ShortTag, close #1039 2017-06-09 09:11:02 +01:00
a302b4988f Fixed bad values assigned to LongTags
PhpStorm you bitch... why didn't you tell me these were a problem?!
2017-06-08 19:28:29 +01:00
2193adf844 Removed auto-generated stub comments 2017-06-08 19:22:52 +01:00
890f72dbf2 Type-hinted NBT tag constructors, made getValue() and setValue() more strict, fix dozens of assorted related bugs 2017-06-08 19:17:52 +01:00
595e1ab52f Added Plugins section to the issue template (#1034)
* Added Plugins section to the issue template

* break it down a little
2017-06-08 18:26:53 +01:00
4a7abb7033 Fix flat worlds crashing when generating 2017-06-08 13:47:13 +01:00
d358e13868 Strict type all the things and fix lots of assorted bugs exposed by strict types (#993)
Strict type all the things
2017-06-08 11:21:51 +01:00
1f630e57f2 Fixed vine block update crashes, close #1032
The meta->side array was the wrong way round (keys & values inverted).
2017-06-08 09:32:38 +01:00
cc1d1b0f45 Fix type error in Furnace due to useless floor(), close #1031 2017-06-08 09:12:58 +01:00
78c09267e5 Typehinted things in BinaryStream, sorted some methods and related bugfixes 2017-06-07 13:53:10 +01:00
c445db421f Fixed stupid bug in resource pack chunk counting, close #1028 2017-06-07 13:29:13 +01:00
e18a3ac933 Fixed UUID-related issues 2017-06-07 13:11:03 +01:00
75863e2a44 OCD commit 2017-06-07 12:54:12 +01:00
5aea9220c9 Fixed chat and some TextContainer documentation issues 2017-06-07 12:54:12 +01:00
bd7205dd64 PhpStorm doesn't understand variable class names :( 2017-06-07 12:54:12 +01:00
82a63ed18e Added an assert to shut PhpStorm up 2017-06-07 12:54:12 +01:00
cf07af8b55 Fix some strict type violations reported by PhpStorm (strict types <3) 2017-06-07 12:54:12 +01:00
b775e8c88a Fix Achievement bug (thanks strict types <3)
as if nobody ever noticed this... LMAO
2017-06-07 12:54:12 +01:00
51091fe87b Fix player data saving 2017-06-07 12:54:12 +01:00
7c14ffbcfa More type fixes 2017-06-07 12:54:12 +01:00
db93827650 Fix world saving 2017-06-07 12:54:12 +01:00
c2186041d6 Fix TranslationContainer issue 2017-06-07 12:53:16 +01:00
481114281e Server starts! 2017-06-07 12:53:16 +01:00
51b0673b4b Bite the bullet and enable strict types on everything 2017-06-07 12:53:16 +01:00
606b9b687d Fix level ticking errors (these methods return floats >_<) 2017-06-07 12:53:15 +01:00
45618c7cfe Enable strict types for Server and add a bunch of type-hints 2017-06-07 12:53:15 +01:00
3f03d9e683 Fixed DevTools getting disabled when a plugin throws an exception during load (#1025) 2017-06-07 11:12:47 +01:00
f0d12a0b30 Implemented asVector3(), asPosition() and asLocation()
Squash merge, closes #973
2017-06-07 16:40:45 +08:00
9cc27b2719 Force sync 'compression' under the batch threshold
Since we aren't actually compressing these anyway, only writing a checksum, sending these asynchronously causes strange bugs due to race conditions.
2017-06-06 11:40:41 +01:00
87e54d7a3a Send block updates in batches 2017-06-06 11:40:30 +01:00
29e88d8592 Send area broadcasted packets in batches
- I don't know why it wasn't done like this to start with
- This provides a significant lightening of workload for large servers with lots of players in the same area because packets are only compressed once instead of for each player.
- Improves client-sided performance receiving these in batches instead of being spammed with many individual packets.
2017-06-05 23:39:16 +01:00
c6e800cf42 Use compression level 0 when batch size is below threshold
This isn't free, because of the adler32 checksum... but it's much lighter on performance for small packets.
2017-06-05 22:05:46 +01:00
b7b7bcee4f Fixed some weak comparisons 2017-06-05 21:07:35 +01:00
6ea0eb47ec Fixed PlayerInventory in_array recursion issue, close #1008
This is INTENDED BEHAVIOUR for comparing objects?????
2017-06-05 20:51:12 +01:00
b9a87ed147 New fields for InventoryActionPacket
TODO: use this packet
2017-06-05 20:04:20 +01:00
742f593758 Added a new constant to ContainerSetContentPacket 2017-06-05 19:15:30 +01:00
1e9ff44890 New field for MobEquipmentPacket
If anyone wants to play with the off-hand, the window ID is 0x77 ;)
2017-06-05 19:10:00 +01:00
55c4e35407 Added a new PlayerActionPacket constant
thanks @jojoe77777
2017-06-05 18:37:53 +01:00
e83ffd5afe Fixed players don't see teleport movement, close #921 2017-06-05 16:47:12 +01:00
54453d0b0a Refactored entity IDs in packets for consistency and to clarify on types 2017-06-05 15:41:27 +01:00
51d510aa4f Who set these stupid values... fixed #1011 2017-06-05 14:22:45 +01:00
4cd97a7c7a Fixed UpdateAttributesPacket not being registered for reading 2017-06-05 14:14:50 +01:00
d586ad03ec Update submodules 2017-06-05 10:15:03 +01:00
61d354a4ea Block constructor mass-replace to fix #963 and related issues 2017-06-05 10:02:27 +01:00
6f126ad239 Fix outdated preprocessor rules for varints, close #1003 2017-06-04 23:27:39 +01:00
efea39e0a4 Change buffer unread assertion to debug
I lost count of how many times I changed this now... what happened to the other times?
2017-06-04 19:19:50 +01:00
d4bb078566 Fixed some formatting issues in Player 2017-06-04 18:32:45 +01:00
6686bd4442 Quick fix for melons and pumpkins, close #965 2017-06-04 16:57:51 +01:00
2b02fcfe2c fixed #992 2017-06-04 16:54:35 +01:00
138fb88431 More default packet fields 2017-06-04 14:53:31 +01:00
26577d9d5b fixed a doc warning 2017-06-04 14:37:06 +01:00
2f4943ac90 Fixed some doc issues 2017-06-04 14:27:30 +01:00
eda7965f86 Fixed wrong types in ParticleCommand 2017-06-04 14:22:12 +01:00
4666560731 Removed some tags that don't exist in vanilla McRegion chunks 2017-06-04 13:04:06 +01:00
b01ad01eff Merge branch 'spammy-backtrace' 2017-06-03 22:04:31 +01:00
4ba3a3af3d fix FloatingTextParticle 2017-06-03 20:51:48 +01:00
5baf59ca56 fix #990 2017-06-03 20:25:24 +01:00
902957cb53 more defaults for optional fields, close #985 2017-06-03 17:41:40 +01:00
3463bea932 add defaults to MobEffectPacket
these fields may be unspecified if we are only removing effects
2017-06-03 15:21:24 +01:00
105917a534 Fixed type issues writing longs and var-longs on 32-bit 2017-06-03 12:04:08 +01:00
b83082f224 Fixed missing field in ContainerSetContentPacket, close #980 2017-06-03 11:59:19 +01:00
840a3883b1 Fixed type of empty ListTags and removed some undefined behaviour (#974)
* Fixed fallback type of empty ListTags, close #972

* Less undefined behaviour
2017-06-03 11:18:00 +01:00
ad4659365a Use default amplifier 0 instead of implicit null
(how did nobody ever notice this?!)
2017-06-03 11:06:22 +01:00
8d858e3e6d Removed __toString() from backtrace, fixes ludicrous amounts of spam when something crashes involving EncapsulatedPackets or NBT 2017-06-03 10:36:04 +01:00
22ba017965 Binary strict types (#969)
* Some Binary cleanup, type-hints and strict types
yes, I know this is very crashy... that's good, because it highlights unexpected behaviour

* added some default values
2017-06-03 09:39:45 +01:00
8bb0e8d398 Fixed a mistake in DropItemPacket encode 2017-06-02 17:52:10 +01:00
087a994393 Workaround for some plugins crashing clients during PlayerLoginEvent 2017-06-02 17:06:01 +01:00
e4e4ef5f2a Fixed preprocessor issues with signed bytes and floats, close #967 2017-06-02 12:50:48 +01:00
3ac51e1095 TAG_Byte should always be signed (#962) 2017-06-02 11:30:44 +01:00
2db6ea6b18 Updated creative inventory data
some items will show wrong damage values due to a bug in meta handling on master
2017-06-02 11:00:36 +01:00
b6ae92e1a7 Updated crafting data and item serialization for 1.1, fixed #963 2017-06-02 10:36:14 +01:00
31e2c1d26c fix stupid bug in PlayerInventory 2017-06-01 20:19:17 +01:00
846e3b6f1e New fields for StartGamePacket 2017-06-01 19:48:06 +01:00
0e525ac1c3 Autogenerated data for 1.1.0.55 2017-06-01 19:24:17 +01:00
8382970d56 Merge branch 'master' into mcpe-1.1 2017-05-30 16:09:46 +01:00
db3cd1829c Made Binary::readVarInt/VarLong methods less useless 2017-05-30 14:19:34 +01:00
caced595d2 Fixed server crash on startup on 32-bit with memory limit set >= 4096MB 2017-05-30 14:15:40 +01:00
86f3b257a7 Remove unneeded foreach loop in Human::getDrops() (#941)
* Remove unneeded foreach loop in Human::getDrops()

* Use array_values() for backwards compatibility.
2017-05-30 13:27:47 +01:00
1ed5de1d3b Merge branch 'nbt-cleanup' 2017-05-30 12:26:17 +01:00
63358a8065 Merge branch 'master' into mcpe-1.1 2017-05-30 09:45:20 +01:00
f6ff03fc31 Added support for MCPACK resource packs 2017-05-30 09:43:28 +01:00
0ad16c1919 Added PlayerDataSaveEvent, resolved #487 (#920)
* Added PlayerDataSaveEvent, resolved #487

* Added getPlayer() to PlayerDataSaveEvent
may return an IPlayer

* Fixed quit messages
This TranslationContainer vs. string mess... >_<
2017-05-29 18:50:45 +01:00
38b8f14758 Fixed wrong reported slot in PlayerItemHeldEvent, fixed assert failures due to negative slot numbers in the hotbar
fixes some issues reported in #525
2017-05-29 16:33:48 +01:00
8779259734 Stop spawning entities to players twice
This will be done when the chunk is sent to the player anyway.
2017-05-29 15:57:05 +01:00
2f306c3a38 Fix crash when new players join due to attempting to send negative inventory slot 2017-05-29 15:30:11 +01:00
57379b93ce Fixed a mistake in metadata decoder 2017-05-27 14:18:40 +01:00
954271b90f Found unknown fields for SetSpawnPositionPacket 2017-05-27 13:13:19 +01:00
645d744e05 Added a check for Phar extension 2017-05-26 21:39:43 +01:00
4c764072b2 Check the entity is actually inside a block before trying to shove it out, fix #271 2017-05-26 17:15:25 +01:00
3446f68c74 Workaround for PowerShell escape code issue after using git in the same window
I don't have any idea why the bug happens. Starting the server in a child PowerShell process resolves the issue.
2017-05-26 13:46:34 +01:00
ca6826898b Added API method Server->broadcastTitle() (#932) 2017-05-25 14:05:41 +01:00
76ab3d4288 This worked fine locally... 2017-05-24 14:50:33 +01:00
b6c1139b27 Fixed lint scan ignoring PHP_BINARY argument 2017-05-24 14:25:48 +01:00
af06d78725 Merge changes from master 2017-05-24 09:54:11 +01:00
8cc1003956 Fixed FloatingTextParticle 2017-05-24 07:37:11 +01:00
92281da514 Fix wrong comment in FallingSand
This is actually a bug in MCPE
2017-05-23 20:02:23 +01:00
5c8297f4a1 Fixed some logic issues with falling blocks, fix #897 #899 #935 2017-05-23 19:48:49 +01:00
23ed3334c2 added creative mode check for block picking 2017-05-23 16:26:29 +01:00
674394c4f5 Fixed undefined offset when retrieving something from the thread store that doesn't exist (#919) 2017-05-22 13:53:57 +08:00
4e381ab033 Added DATA_COLOR alias 2017-05-21 14:40:49 +01:00
c5527db424 Be more clear about ProtocolInfo being automatically generated and add notice to not bother submitting PRs for changing version numbers (#931) 2017-05-21 13:58:01 +01:00
aecff7c782 Revert "Improved handling of incompatible protocols"
This reverts commit 576702ffa9.

This crippled plugins which use data fromm LoginPacket :S
2017-05-21 13:27:27 +01:00
0207b22110 Fixed Mojang world converters barfing on PocketMine-MP generated McRegion worlds
blame @shoghicp
2017-05-21 12:44:42 +01:00
a77c1ce13c remove leftover 2017-05-20 12:24:10 +01:00
afd90adb1c Refactored JSON-parsing NBT utilities into their own class 2017-05-20 12:24:10 +01:00
2e480b5ea1 Fixed broken logic for recursive counts of ListTag 2017-05-20 12:24:10 +01:00
d4cc7d13cd Fixed setValue() being useless for CompoundTags and ListTags 2017-05-20 12:24:10 +01:00
f6c0ba9846 Cleaned up some duplicated code in NBT parser 2017-05-20 12:24:01 +01:00
f3c38700f5 Removed options for disabling assertion exceptions 2017-05-20 12:24:00 +01:00
77b1b565a4 Stop silently blocking people 2017-05-19 12:11:40 +01:00
36c95660e6 Fixed some logic issues with async compression 2017-05-19 11:30:23 +01:00
905d3f1610 Only save batch buffer when compressing chunks
faster due to not needing to serialize, and reduces memory footprint of caching
2017-05-18 19:46:20 +01:00
0f174f7605 Fixed ServerKiller always killing on shutdown on single-core machines, close #170 2017-05-18 15:58:09 +01:00
60f5c7ccef Async chunk compression and serialization is now non-optional 2017-05-18 12:19:27 +01:00
85c1535c75 Merge branch 'master' into mcpe-1.1 2017-05-18 11:29:52 +01:00
568e2760f1 Collect workers when cancelling all tasks 2017-05-17 19:30:50 +01:00
fe8cb8cd86 Server->batchPackets() now only accepts DataPacket objects, fixed players receiving double PlayerListPackets with their own data 2017-05-17 17:15:42 +01:00
15b47fcb2f Merge branch 'master' into mcpe-1.1 2017-05-17 15:52:01 +01:00
00e6d6a6b1 Fixed AsyncTask memory leak (#922)
* Added PocketMine-TesterPlugin submodule with regression test
2017-05-17 15:43:44 +01:00
8887a92d4b Removed useless break statements 2017-05-16 21:20:22 +01:00
a9afad10bc BinaryStream no longer extends stdClass, fixed a couple of minor bugs
Seems :shoghi: used stdClass to silence IDEs, which before ALPHA5 would complain about myriad undefined fields due to lack of type checking (switch based on packet id 🤦)
2017-05-15 19:28:39 +01:00
b41fef0276 Fixed some field types 2017-05-15 16:38:02 +01:00
fe3b5bac51 New fields for PlaySoundPacket and StopSoundPacket 2017-05-15 16:19:08 +01:00
0a4d62b405 Added encode and decode methods for more packets 2017-05-15 15:56:59 +01:00
0935855def Fix issue with colored message on some languages (#910) 2017-05-15 10:07:01 +01:00
c7c7a40899 Added "extensions" attribute in plugin.yml with version checking (#903)
* Added "extensions" attribute in plugin.yml with version checking

* Renamed getExtensions() to getRequiredExtensions()

As per recommendation from @dktapps
2017-05-15 10:04:26 +01:00
162a08b8cb Removed options for disabling assertion exceptions 2017-05-14 20:48:58 +01:00
b9ad0b99a5 Merge master into mcpe-1.1 2017-05-14 16:42:42 +01:00
576702ffa9 Improved handling of incompatible protocols
Allow plugins to hack around incompatible protocol numbers 🙈
2017-05-14 16:15:15 +01:00
dbb8e8ad0a Improved checks for event registration 2017-05-14 12:07:15 +01:00
4a9acf564c Silence PlayerFallPacket unhandled spam
we're not using this packet
2017-05-13 19:26:57 +01:00
69f64dd802 BossEventPacket
lots of stuff doesn't work (not implemented in MCPE, bug, or are we doing something wrong???)
2017-05-13 17:33:56 +01:00
11169b0777 add ifndef for BatchPacket 2017-05-13 14:57:48 +01:00
71af694cc1 Use getBool() more 2017-05-10 11:30:24 +01:00
c51c8ae700 Standardised attributes encoding 2017-05-10 10:48:53 +01:00
713f3facf9 Fixed stupid bug with Arrows 2017-05-09 21:09:34 +01:00
df577bddc2 Updated LevelSoundEventPacket constants (again) 2017-05-09 14:02:51 +01:00
046f17c9e2 Merge branch 'master' into mcpe-1.1 2017-05-08 17:43:09 +01:00
50f7d04044 Import cleanup 2017-05-07 16:55:10 +01:00
4ccd955647 Fixed possible memory leak with projectiles, use owner/target metadata 2017-05-07 16:50:32 +01:00
c383c7b0dd Found an unknown field in LevelSoundEventPacket 2017-05-05 18:34:52 +01:00
adbb53929e Fixed scaling issues with height and width on the client, close #819
Seems these metadata fields are actually the _base_ height/width. Setting the scale will cause the client to calculate bounding boxes with the scale already taken into account. This caused the scale to be applied twice on the client.
2017-05-05 16:51:15 +01:00
8a7259aa73 Merge #826: use getEffectLevel() instead of getAmplifier() + 1
Closes #412
2017-05-05 19:01:04 +08:00
76ceddf266 Reduced deltas for player movement, significantly smoother player movement and rotation (#883)
Send movement to viewers if the player moved more than 0.01 blocks in a tick or rotated more than 1 degree in any direction.
2017-05-05 11:23:06 +01:00
11f35d28c2 Call PlayerInteractEventm when receiving ItemFrameDropItemPacket to allow plugins to prevent item frame item removal (#887) 2017-05-05 11:18:58 +01:00
c4f461f65d Fixed fall damage in 1 block of water, close #470 2017-05-05 10:41:44 +01:00
702c129a97 Added basic support back for block-crack animations when breaking blocks
TODO: improve this to take stuff like swimming, ladders, enchanted tools into account, fix wrong tool break time calculations for bad tools (pmmp/PocketMine-MP#211)
2017-05-05 09:40:55 +01:00
56306f6636 Merge branch 'master' into mcpe-1.1 2017-05-04 21:15:49 +01:00
18f1376c65 Added handling for punch-block player action, added block punch particles 2017-05-04 21:11:47 +01:00
49eb0eb050 Fixed falling sand glitching on landing, minor logic improvements 2017-05-04 17:48:39 +01:00
13fd8b681e Added some sounds, fixed DestroyBlockParticle wrong particles for blocks with different meta values 2017-05-04 16:50:13 +01:00
40f2d7fcdc Updated LevelSoundEventPacket sound constants 2017-05-04 16:00:49 +01:00
c537cea87e Resolved issues with incorrect item and TNT position offsets, close #848 2017-05-04 13:52:10 +01:00
eaef2bd169 Fixed some inspections 2017-05-04 12:19:50 +01:00
966e4bf8a1 Added name field to crashdump data 2017-05-02 19:37:35 +01:00
f889bf9cf5 Fixed player list self-duplication 2017-05-02 12:28:27 +01:00
6d90f91be0 Fixed crashes while crashing related to plugins 2017-04-30 16:22:50 +01:00
0a52e210db Fixed crash when crashing while generating a crashdump due to crashing 2017-04-30 16:01:08 +01:00
971703a618 Dump object counts when dumping memory 2017-04-29 19:12:46 +01:00
de359a2bce Fixed a microscopic Command TimingsHandler memory leak
This reduces memory usage of an idling server by about 20kb. Definitely worth the time.
2017-04-29 18:03:45 +01:00
1266f8f1aa Fixed static properties not being dumped if an instance of the class was not referenced by Server 2017-04-29 12:25:00 +01:00
a22306d418 Fixed static property refcount bug 2017-04-28 18:43:36 +01:00
b542277eca Disable memory limit before performing a mem dump
Fix memory dumps not completing due to exhausting available memory
2017-04-28 16:53:05 +01:00
edf1fbb6e6 Removed a couple of useless null checks from PermissibleBase 2017-04-27 18:00:20 +01:00
653b6b55a9 Added title command and API for resetting title duration 2017-04-27 16:38:51 +01:00
7f09a2a26e Added Announcement type to TextPacket 2017-04-27 16:10:42 +01:00
7aeb3129ac Merge conflict resolution 2017-04-27 14:27:29 +01:00
dc71eb5246 Protocol updates for 1.1.0.9 2017-04-27 11:24:49 +01:00
bf9b8722c9 Cleaned up batching checks 2017-04-26 22:02:45 +01:00
4d897b824b Added more metadata properties, fixed some wrong values, fixed too many oxygen bubbles 2017-04-26 19:48:31 +01:00
caf4937222 Fixed arrow flight and spawning bugs, fixed critical trail, close #420 2017-04-26 18:55:48 +01:00
2f87dfdcb0 Merge branch 'master' into mcpe-1.1 2017-04-25 18:05:32 +01:00
ffcada88f3 New data flags 2017-04-25 16:27:29 +01:00
946d7e2bb1 Merge changes from master 2017-04-25 12:32:10 +01:00
7a2ed232cc Merge branch 'api3/network' into api3/network-mcpe-1.1 2017-04-24 13:56:19 +01:00
1be4bd67e4 Fixed assert failure when player join in un-generated areas of the world 2017-04-24 10:32:50 +01:00
fcff6961a8 Bump for 1.1.0.8 and removed LoginPacket zlib hack 2017-04-22 11:10:13 +01:00
db4027cdb2 New fields for MovePlayer and MoveEntity packets 2017-04-22 00:58:18 +01:00
e22bb213af Oops 2017-04-22 00:47:01 +01:00
179210aa27 Merge branch 'api3/network' into api3/network-mcpe-1.1 2017-04-21 22:50:14 +01:00
be631ad6f7 Fixed disconnects properly 2017-04-21 20:31:47 +01:00
3f1790bcb8 Found some missing data flags and proper fix for ladders 2017-04-20 19:42:00 +01:00
a0ba8f0098 Added some new metadata, fixed others, fixed TNT (again) 2017-04-20 17:52:24 +01:00
feb538900b Added a couple of entity metadata properties 2017-04-20 16:05:46 +01:00
5ce860c2f5 Updated AnimatePacket with extra float handling 2017-04-20 15:39:12 +01:00
6c5ca9b256 Protocol updates for 1.1.0.5 2017-04-20 13:54:55 +01:00
17e4f45e97 Fixed kicking players not working properly 2017-04-18 19:41:09 +01:00
6828ce66b6 Fixed farmland appearing black on clients (farmland is transparent in PE) 2017-04-18 19:40:54 +01:00
b7b7a93e4e Merge branch 'api3/network' into api3/network-mcpe-1.1 2017-04-18 14:52:06 +01:00
a34573643f Fixed transparent blocks filtering direct sky light 2017-04-18 14:14:19 +01:00
dab73d8950 Implemented sky light generation-time population and updating, obsolete and close #160 2017-04-18 13:05:01 +01:00
5e6a0e7ba0 More metadata changes, fixed TNT 2017-04-16 22:03:52 +01:00
c5eccc8e1c Minor improvements to Batch encoding 2017-04-15 19:40:06 +01:00
b55929b382 Merge branch 'api3/network' into api3/network-mcpe-1.1 2017-04-15 10:30:02 +01:00
d7378fe6f4 Some new metadata properties 2017-04-14 19:56:23 +01:00
66924729ff Fixed climbing blocks such as ladders and vines
Seems we can now climb ANY block if the climbing flag is true, and nothing if false. This commit adds local block checks to see if a climbable block exists at the entity's feet and if so, sets the flag.
2017-04-14 19:02:53 +01:00
f12a6eed29 Fixed vine block placement 2017-04-14 18:25:50 +01:00
a327a74ece Protocol changes for 1.1.0.3, fixed red sky, fixed crashes 2017-04-14 15:17:56 +01:00
f3ab45e7d5 Merged in 1.0.6 changes, added autogenerated data for 1.1.0.3 (doesn't work yet) and deliberately made the same merge error as Mojang 2017-04-14 13:00:43 +01:00
cdf6d200ef More protocol changes for 1.1, fixed resource packs 2017-04-14 12:48:50 +01:00
894beed59b Removed time stopping fields from SetTimePacket and fixed #526
TODO: rules
2017-04-11 20:13:37 +01:00
022f33b256 Fixed encoding of StartGamePacket, fixed world name not showing up in settings screen 2017-04-03 16:04:15 +01:00
90f1efc667 Found use of extra bytes in Item serialization
No idea why these are separate from the NBT data, but this is what they do.
2017-04-02 19:29:14 +01:00
f7e959d602 Fixed inventory crash, fixed crafting 2017-04-02 10:58:39 +01:00
9c25ec3afd Some protocol changes for 1.1.0.0 2017-04-01 19:20:30 +01:00
e47c7ea55f A bunch of really dirty hacks to get 1.1.0.0 working
Mojang: once again, what the hell have you done.
2017-04-01 19:18:15 +01:00
882 changed files with 11657 additions and 4262 deletions

View File

@ -16,15 +16,26 @@ Actual result: What actually happened?
### OS and versions
<!--- use the 'version' command in PocketMine-MP
NOTE: LATEST is not a valid version.
PocketMine version should include Jenkins build number and/or git commit hash.
ALSO NOTE: NO support whatsoever will be provided for forks or spoons of PocketMine. Issues relating to non-official distributions will be closed as spam. Please send such issues to whoever is responsible for the fork or spoon you are using.
NOTE: LATEST is not a valid version. PocketMine version should include Jenkins build number and/or git commit hash.
NO support whatsoever will be provided for forks or spoons of PocketMine. Issues relating to non-official distributions will be closed as spam. Please send such issues to whoever is responsible for the fork or spoon you are using.
Note that 32-bit platforms are no longer supported by PocketMine-MP and issues concerning 32-bit platforms will be closed.
-->
* PocketMine-MP:
* PHP:
* Server OS:
* Game version: PE/Win10 (delete as appropriate)
### Plugins
- Test on a clean server without plugins: is the issue reproducible without any plugins loaded?
If the issue is **not** reproducible without plugins:
- Have you asked for help on our forums before creating an issue?
- Can you provide sample, *minimal* reproducing code for the issue? If so, paste it in the bottom section
- Paste your list of plugins here (use the 'plugins' command in PocketMine-MP)
### Crashdump, backtrace or other files
<!--- please use gist or anything else and add links here -->
* ...

3
.gitmodules vendored
View File

@ -14,3 +14,6 @@
[submodule "tests/plugins/PocketMine-DevTools"]
path = tests/plugins/PocketMine-DevTools
url = https://github.com/pmmp/PocketMine-DevTools.git
[submodule "tests/plugins/PocketMine-TesterPlugin"]
path = tests/plugins/PocketMine-TesterPlugin
url = https://github.com/pmmp/PocketMine-TesterPlugin.git

View File

@ -18,8 +18,10 @@
- Information must be provided in the issue body, not in the title. No tags like `[BUG]` are allowed in the title, including `[SOLVED]` for solved issues.
- Similarly, no generic issue reports. For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**. If you do not provide us with a summary or instructions on how to reproduce the issue, it will be treated as spam and will therefore be closed.
<br>In simple words, if your issue does not appear to be a bug or a feature request, or if the issue cannot be properly confirmed to be valid, the issue will be closed until further information is provided.
- Similarly, no generic issue reports. For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**.
<br><br>Valid issue reports must include instructions how to reproduce the issue or a crashdump/backtrace (unless the cause of the issue is obvious).
<br><br>**If you do not provide us with a summary or instructions on how to reproduce the issue, it will be treated as spam and will therefore be closed.**
<br><br>In simple words, if the issue cannot be properly confirmed to be valid or lacks required information, the issue will be closed until further information is provided.
- To express appreciation, objection, confusion or other supported reactions on pull requests, issues or comments on them, use GitHub [reactions](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) rather than posting an individual comment with an emoji only. This helps keeping the issue/pull request conversation clean and readable.

View File

@ -13,7 +13,7 @@ If you don't find what you're looking for there, [talk to a human](#discussion).
- [#pmmp + #pocketmine channel IRC](http://webchat.freenode.net/?channels=pmmp,pocketmine)
### Plugins
There are a very wide range of already-written plugins available which you can use to customise your server. Check out [the old plugin repository](http://plugins.pocketmine.net/) and [Poggit](https://poggit.pmmp.io), or just search GitHub.
There are a very wide range of already-written plugins available which you can use to customise your server. Check out [Poggit](https://poggit.pmmp.io), or just search GitHub.
### For developers
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine;
use pocketmine\event\TranslationContainer;
@ -107,8 +109,8 @@ abstract class Achievement{
public static function broadcast(Player $player, $achievementId){
if(isset(Achievement::$list[$achievementId])){
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"]]);
if(Server::getInstance()->getConfigString("announce-player-achievements", true) === true){
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
if(Server::getInstance()->getConfigBoolean("announce-player-achievements", true) === true){
Server::getInstance()->broadcastMessage($translation);
}else{
$player->sendMessage($translation);

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine;
abstract class Collectable extends \Threaded implements \Collectable{

View File

@ -19,11 +19,14 @@
*
*/
declare(strict_types=1);
namespace pocketmine;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\plugin\PluginBase;
use pocketmine\plugin\PluginLoadOrder;
use pocketmine\plugin\PluginManager;
use pocketmine\utils\Utils;
use pocketmine\utils\VersionString;
use raklib\RakLib;
@ -86,7 +89,7 @@ class CrashDump{
}
private function pluginsData(){
if(class_exists("pocketmine\\plugin\\PluginManager", false)){
if($this->server->getPluginManager() instanceof PluginManager){
$this->addLine();
$this->addLine("Loaded plugins:");
$this->data["plugins"] = [];
@ -224,6 +227,7 @@ class CrashDump{
private function generalData(){
$version = new VersionString();
$this->data["general"] = [];
$this->data["general"]["name"] = $this->server->getName();
$this->data["general"]["version"] = $version->get(false);
$this->data["general"]["build"] = $version->getBuild();
$this->data["general"]["protocol"] = ProtocolInfo::CURRENT_PROTOCOL;
@ -235,7 +239,7 @@ class CrashDump{
$this->data["general"]["zend"] = zend_version();
$this->data["general"]["php_os"] = PHP_OS;
$this->data["general"]["os"] = Utils::getOS();
$this->addLine("PocketMine-MP version: " . $version->get(false) . " #" . $version->getBuild() . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
$this->addLine($this->server->getName() . " version: " . $version->get(false) . " #" . $version->getBuild() . " [Protocol " . ProtocolInfo::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
$this->addLine("Git commit: " . GIT_COMMIT);
$this->addLine("uname -a: " . php_uname("a"));
$this->addLine("PHP Version: " . phpversion());

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine;
use pocketmine\permission\ServerOperator;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine;
use pocketmine\event\server\LowMemoryEvent;
@ -90,7 +92,7 @@ class MemoryManager{
$hardLimit = ((int) $this->server->getProperty("memory.main-hard-limit", $defaultMemory));
if($hardLimit <= 0){
ini_set("memory_limit", -1);
ini_set("memory_limit", '-1');
}else{
ini_set("memory_limit", $hardLimit . "M");
}
@ -214,6 +216,8 @@ class MemoryManager{
}
public function dumpServerMemory($outputFolder, $maxNesting, $maxStringSize){
$hardLimit = ini_get('memory_limit');
ini_set('memory_limit', '-1');
gc_disable();
if(!file_exists($outputFolder)){
@ -232,6 +236,32 @@ class MemoryManager{
$refCounts = [];
$instanceCounts = [];
$staticCount = 0;
foreach($this->server->getLoader()->getClasses() as $className){
$reflection = new \ReflectionClass($className);
$staticProperties[$className] = [];
foreach($reflection->getProperties() as $property){
if(!$property->isStatic() or $property->getDeclaringClass()->getName() !== $className){
continue;
}
if(!$property->isPublic()){
$property->setAccessible(true);
}
$staticCount++;
$this->continueDump($property->getValue(), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
if(count($staticProperties[$className]) === 0){
unset($staticProperties[$className]);
}
}
echo "[Dump] Wrote $staticCount static properties\n";
$this->continueDump($this->server, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
do{
@ -243,6 +273,11 @@ class MemoryManager{
$continue = true;
$className = get_class($object);
if(!isset($instanceCounts[$className])){
$instanceCounts[$className] = 1;
}else{
$instanceCounts[$className]++;
}
$objects[$hash] = true;
@ -273,33 +308,23 @@ class MemoryManager{
}
fwrite($obData, "$hash@$className: " . json_encode($info, JSON_UNESCAPED_SLASHES) . "\n");
if(!isset($objects["staticProperties"][$className])){
$staticProperties[$className] = [];
foreach($reflection->getProperties() as $property){
if(!$property->isStatic() or $property->getDeclaringClass()->getName() !== $className){
continue;
}
if(!$property->isPublic()){
$property->setAccessible(true);
}
$this->continueDump($property->getValue($object), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
}
}
echo "[Dump] Wrote " . count($objects) . " objects\n";
}while($continue);
fclose($obData);
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents($outputFolder . "/serverEntry.js", json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents($outputFolder . "/referenceCounts.js", json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
arsort($instanceCounts, SORT_NUMERIC);
file_put_contents($outputFolder . "/instanceCounts.js", json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
echo "[Dump] Finished!\n";
ini_set('memory_limit', $hardLimit);
gc_enable();
}

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine;
use pocketmine\metadata\Metadatable;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine;
use pocketmine\block\Air;
@ -112,9 +114,11 @@ use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
use pocketmine\network\mcpe\protocol\BlockEventPacket;
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
use pocketmine\network\mcpe\protocol\BossEventPacket;
use pocketmine\network\mcpe\protocol\ChangeDimensionPacket;
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
use pocketmine\network\mcpe\protocol\ClientboundMapItemDataPacket;
@ -148,7 +152,7 @@ use pocketmine\network\mcpe\protocol\MobEquipmentPacket;
use pocketmine\network\mcpe\protocol\MoveEntityPacket;
use pocketmine\network\mcpe\protocol\MovePlayerPacket;
use pocketmine\network\mcpe\protocol\PlayerActionPacket;
use pocketmine\network\mcpe\protocol\PlayerFallPacket;
use pocketmine\network\mcpe\protocol\EntityFallPacket;
use pocketmine\network\mcpe\protocol\PlayerInputPacket;
use pocketmine\network\mcpe\protocol\PlayerListPacket;
use pocketmine\network\mcpe\protocol\PlaySoundPacket;
@ -184,7 +188,6 @@ use pocketmine\network\mcpe\protocol\StopSoundPacket;
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
use pocketmine\network\mcpe\protocol\TextPacket;
use pocketmine\network\mcpe\protocol\TransferPacket;
use pocketmine\network\mcpe\protocol\UnknownPacket;
use pocketmine\network\mcpe\protocol\UpdateAttributesPacket;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\network\mcpe\protocol\UpdateTradePacket;
@ -287,6 +290,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
protected $stepHeight = 0.6;
protected $baseOffset = 1.62;
public $usedChunks = [];
protected $chunkLoadCount = 0;
protected $loadQueue = [];
@ -763,10 +768,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
$this->usedChunks = [];
$pk = new SetTimePacket();
$pk->time = $this->level->getTime();
$pk->started = $this->level->stopTime == false;
$this->dataPacket($pk);
$this->level->sendTime($this);
}
}
@ -806,7 +808,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return $this->spawnPosition instanceof WeakPosition and $this->spawnPosition->isValid();
}
public function sendChunk($x, $z, $payload){
public function sendChunk(int $x, int $z, BatchPacket $payload){
if($this->connected === false){
return;
}
@ -814,15 +816,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->usedChunks[Level::chunkHash($x, $z)] = true;
$this->chunkLoadCount++;
if($payload instanceof DataPacket){
$this->dataPacket($payload);
}else{
$pk = new FullChunkDataPacket();
$pk->chunkX = $x;
$pk->chunkZ = $z;
$pk->data = $payload;
$this->batchDataPacket($pk);
}
$this->dataPacket($payload);
if($this->spawned){
foreach($this->level->getChunkEntities($x, $z) as $entity){
@ -849,6 +843,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$X = null;
$Z = null;
Level::getXZ($index, $X, $Z);
assert(is_int($X) and is_int($Z));
++$count;
@ -879,27 +874,19 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->sendSettings();
$this->sendPotionEffects($this);
$this->sendData($this);
$this->inventory->sendContents($this);
$this->inventory->sendArmorContents($this);
$this->inventory->sendHeldItem($this);
$pk = new SetTimePacket();
$pk->time = $this->level->getTime();
$pk->started = $this->level->stopTime == false;
$this->dataPacket($pk);
$pos = $this->level->getSafeSpawn($this);
$this->server->getPluginManager()->callEvent($ev = new PlayerRespawnEvent($this, $pos));
$pos = $ev->getRespawnPosition();
$pk = new RespawnPacket();
$pk->x = $pos->x;
$pk->y = $pos->y;
$pk->z = $pos->z;
$this->dataPacket($pk);
$this->sendRespawnPacket($pos);
$this->sendPlayStatus(PlayStatusPacket::PLAYER_SPAWN);
@ -915,7 +902,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->getDisplayName()
])
));
if(strlen(trim($ev->getJoinMessage())) > 0){
if(strlen(trim((string) $ev->getJoinMessage())) > 0){
$this->server->broadcastMessage($ev->getJoinMessage());
}
@ -934,22 +921,25 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->spawnToAll();
if($this->server->getUpdater()->hasUpdate() and $this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE)){
if($this->server->getUpdater()->hasUpdate() and $this->hasPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE) and $this->server->getProperty("auto-updater.on-update.warn-ops", true)){
$this->server->getUpdater()->showPlayerUpdate($this);
}
if($this->getHealth() <= 0){
$pk = new RespawnPacket();
$pos = $this->getSpawn();
$pk->x = $pos->x;
$pk->y = $pos->y;
$pk->z = $pos->z;
$this->dataPacket($pk);
$this->sendRespawnPacket($this->getSpawn());
}
$this->joined = true;
}
protected function sendRespawnPacket(Vector3 $pos){
$pk = new RespawnPacket();
$pk->x = $pos->x;
$pk->y = $pos->y + $this->baseOffset;
$pk->z = $pos->z;
$this->dataPacket($pk);
}
protected function orderChunks(){
if($this->connected === false or $this->viewDistance === -1){
return false;
@ -1195,6 +1185,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk->x = (int) $this->spawnPosition->x;
$pk->y = (int) $this->spawnPosition->y;
$pk->z = (int) $this->spawnPosition->z;
$pk->spawnType = SetSpawnPositionPacket::TYPE_PLAYER_SPAWN;
$pk->spawnForced = false;
$this->dataPacket($pk);
}
@ -1209,7 +1201,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->level->sleepTicks = 0;
$pk = new AnimatePacket();
$pk->eid = $this->id;
$pk->entityRuntimeId = $this->id;
$pk->action = 3; //Wake up
$this->dataPacket($pk);
}
@ -1248,6 +1240,26 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return $this->gamemode;
}
/**
* @internal
*
* Returns a client-friendly gamemode of the specified real gamemode
* This function takes care of handling gamemodes known to MCPE (as of 1.1.0.3, that includes Survival, Creative and Adventure)
*
* TODO: remove this when Spectator Mode gets added properly to MCPE
*
* @param int $gamemode
* @return int
*/
public static function getClientFriendlyGamemode(int $gamemode) : int{
$gamemode &= 0x03;
if($gamemode === Player::SPECTATOR){
return Player::CREATIVE;
}
return $gamemode;
}
/**
* Sets the gamemode, and if needed, kicks the Player.
*
@ -1261,13 +1273,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return false;
}
$this->server->getPluginManager()->callEvent($ev = new PlayerGameModeChangeEvent($this, (int) $gm));
$this->server->getPluginManager()->callEvent($ev = new PlayerGameModeChangeEvent($this, $gm));
if($ev->isCancelled()){
if($client){ //gamemode change by client in the GUI
$pk = new SetPlayerGameTypePacket();
$pk->gamemode = $this->gamemode & 0x01;
$this->dataPacket($pk);
$this->sendSettings();
$this->sendGamemode();
}
return false;
}
@ -1294,9 +1303,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->namedtag->playerGameType = new IntTag("playerGameType", $this->gamemode);
if(!$client){ //Gamemode changed by server, do not send for client changes
$pk = new SetPlayerGameTypePacket();
$pk->gamemode = $this->gamemode & 0x01;
$this->dataPacket($pk);
$this->sendGamemode();
}else{
Command::broadcastCommandMessage($this, new TranslationContainer("commands.gamemode.success.self", [Server::getGamemodeString($gm)]));
}
@ -1313,6 +1320,16 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return true;
}
/**
* @internal
* Sends the player's gamemode to the client.
*/
public function sendGamemode(){
$pk = new SetPlayerGameTypePacket();
$pk->gamemode = Player::getClientFriendlyGamemode($this->gamemode);
$this->dataPacket($pk);
}
/**
* Sends all the option flags
*/
@ -1320,6 +1337,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk = new AdventureSettingsPacket();
$pk->flags = 0;
$pk->worldImmutable = $this->isSpectator();
$pk->noPvp = $this->isSpectator();
$pk->autoJump = $this->autoJump;
$pk->allowFlight = $this->allowFlight;
$pk->noClip = $this->isSpectator();
@ -1545,7 +1563,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$delta = pow($this->lastX - $to->x, 2) + pow($this->lastY - $to->y, 2) + pow($this->lastZ - $to->z, 2);
$deltaAngle = abs($this->lastYaw - $to->yaw) + abs($this->lastPitch - $to->pitch);
if(!$revert and ($delta > (1 / 16) or $deltaAngle > 10)){
if(!$revert and ($delta > 0.0001 or $deltaAngle > 1.0)){
$isFirst = ($this->lastX === null or $this->lastY === null or $this->lastZ === null);
@ -1565,10 +1583,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
if($to->distanceSquared($ev->getTo()) > 0.01){ //If plugins modify the destination
$this->teleport($ev->getTo());
}else{
$this->level->addEntityMovement($this->x >> 4, $this->z >> 4, $this->getId(), $this->x, $this->y + $this->getEyeHeight(), $this->z, $this->yaw, $this->pitch, $this->yaw);
$this->level->addEntityMovement($this->x >> 4, $this->z >> 4, $this->getId(), $this->x, $this->y + $this->baseOffset, $this->z, $this->yaw, $this->pitch, $this->yaw);
$distance = $from->distance($to);
//TODO: check swimming (adds 0.015 exhaustion in MCPE)
if($this->isSprinting()){
$this->exhaust(0.1 * $distance, PlayerExhaustEvent::CAUSE_SPRINTING);
@ -1628,7 +1645,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$entries = $sendAll ? $this->attributeMap->getAll() : $this->attributeMap->needSend();
if(count($entries) > 0){
$pk = new UpdateAttributesPacket();
$pk->entityId = $this->id;
$pk->entityRuntimeId = $this->id;
$pk->entries = $entries;
$this->dataPacket($pk);
foreach($entries as $entry){
@ -1796,7 +1813,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->allowFlight = (bool) ($this->gamemode & 0x01);
if(($level = $this->server->getLevelByName($this->namedtag["Level"])) === null){
if(($level = $this->server->getLevelByName((string) $this->namedtag["Level"])) === null){
$this->setLevel($this->server->getDefaultLevel());
$this->namedtag["Level"] = $this->level->getName();
$this->namedtag["Pos"][0] = $this->level->getSpawnLocation()->x;
@ -1813,7 +1830,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->achievements[$achievement->getName()] = $achievement->getValue() > 0 ? true : false;
}
$this->namedtag->lastPlayed = new LongTag("lastPlayed", floor(microtime(true) * 1000));
$this->namedtag->lastPlayed = new LongTag("lastPlayed", (int) floor(microtime(true) * 1000));
if($this->server->getAutoSave()){
$this->server->saveOfflinePlayerData($this->username, $this->namedtag, true);
}
@ -1831,15 +1848,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
protected function completeLoginSequence(){
parent::__construct($this->level, $this->namedtag);
$this->server->getPluginManager()->callEvent($ev = new PlayerLoginEvent($this, "Plugin reason"));
if($ev->isCancelled()){
$this->close($this->getLeaveMessage(), $ev->getKickMessage());
return;
}
if(!$this->hasValidSpawnPosition() and isset($this->namedtag->SpawnLevel) and ($level = $this->server->getLevelByName($this->namedtag["SpawnLevel"])) instanceof Level){
$this->spawnPosition = new WeakPosition($this->namedtag["SpawnX"], $this->namedtag["SpawnY"], $this->namedtag["SpawnZ"], $level);
if(!$this->hasValidSpawnPosition()){
if(isset($this->namedtag->SpawnLevel) and ($level = $this->server->getLevelByName((string) $this->namedtag["SpawnLevel"])) instanceof Level){
$this->spawnPosition = new WeakPosition($this->namedtag["SpawnX"], $this->namedtag["SpawnY"], $this->namedtag["SpawnZ"], $level);
}else{
$this->spawnPosition = WeakPosition::fromObject($this->level->getSafeSpawn());
}
}
$spawnPosition = $this->getSpawn();
@ -1847,34 +1862,42 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk = new StartGamePacket();
$pk->entityUniqueId = $this->id;
$pk->entityRuntimeId = $this->id;
$pk->playerGamemode = Player::getClientFriendlyGamemode($this->gamemode);
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$pk->pitch = $this->pitch;
$pk->yaw = $this->yaw;
$pk->seed = -1;
$pk->dimension = 0; //TODO: implement this properly
$pk->gamemode = $this->gamemode & 0x01;
$pk->worldGamemode = Player::getClientFriendlyGamemode($this->server->getGamemode());
$pk->difficulty = $this->server->getDifficulty();
$pk->spawnX = $spawnPosition->getFloorX();
$pk->spawnY = $spawnPosition->getFloorY();
$pk->spawnZ = $spawnPosition->getFloorZ();
$pk->hasBeenLoadedInCreative = 1;
$pk->hasAchievementsDisabled = true;
$pk->dayCycleStopTime = -1; //TODO: implement this properly
$pk->eduMode = 0;
$pk->eduMode = false;
$pk->rainLevel = 0; //TODO: implement these properly
$pk->lightningLevel = 0;
$pk->commandsEnabled = 1;
$pk->commandsEnabled = true;
$pk->levelId = "";
$pk->worldName = $this->server->getMotd();
$this->dataPacket($pk);
$pk = new SetTimePacket();
$pk->time = $this->level->getTime();
$pk->started = $this->level->stopTime == false;
$this->dataPacket($pk);
$this->server->getPluginManager()->callEvent($ev = new PlayerLoginEvent($this, "Plugin reason"));
if($ev->isCancelled()){
$this->close($this->getLeaveMessage(), $ev->getKickMessage());
return;
}
$this->level->sendTime($this);
$this->sendAttributes(true);
$this->setNameTagVisible(true);
$this->setNameTagAlwaysVisible(true);
$this->setCanClimb(true);
$this->server->getLogger()->info($this->getServer()->getLanguage()->translateString("pocketmine.player.logIn", [
TextFormat::AQUA . $this->username . TextFormat::WHITE,
@ -1909,15 +1932,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return false;
}
$this->username = TextFormat::clean($packet->username);
$this->displayName = $this->username;
$this->iusername = strtolower($this->username);
$this->setDataProperty(self::DATA_NAMETAG, self::DATA_TYPE_STRING, $this->username, false);
if(count($this->server->getOnlinePlayers()) >= $this->server->getMaxPlayers() and $this->kick("disconnectionScreen.serverFull", false)){
return true;
}
if($packet->protocol !== ProtocolInfo::CURRENT_PROTOCOL){
if($packet->protocol < ProtocolInfo::CURRENT_PROTOCOL){
$message = "disconnectionScreen.outdatedClient";
@ -1931,6 +1945,15 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return true;
}
$this->username = TextFormat::clean($packet->username);
$this->displayName = $this->username;
$this->iusername = strtolower($this->username);
$this->setDataProperty(self::DATA_NAMETAG, self::DATA_TYPE_STRING, $this->username, false);
if(count($this->server->getOnlinePlayers()) >= $this->server->getMaxPlayers() and $this->kick("disconnectionScreen.serverFull", false)){
return true;
}
$this->randomClientId = $packet->clientId;
$this->uuid = UUID::fromString($packet->clientUUID);
@ -2016,7 +2039,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk = new ResourcePackDataInfoPacket();
$pk->packId = $pack->getPackId();
$pk->maxChunkSize = 1048576; //1MB
$pk->chunkCount = $pack->getPackSize() / $pk->maxChunkSize;
$pk->chunkCount = (int) ceil($pack->getPackSize() / $pk->maxChunkSize);
$pk->compressedPackSize = $pack->getPackSize();
$pk->sha256 = $pack->getSha256();
$this->dataPacket($pk);
@ -2119,7 +2142,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
public function handleMovePlayer(MovePlayerPacket $packet) : bool{
$newPos = new Vector3($packet->x, $packet->y - $this->getEyeHeight(), $packet->z);
$newPos = new Vector3($packet->x, $packet->y - $this->baseOffset, $packet->z);
$revert = false;
if(!$this->isAlive() or $this->spawned !== true){
@ -2262,7 +2285,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
if($packet->inventorySlot === 255){
$packet->inventorySlot = -1; //Cleared slot
}else{
if($packet->inventorySlot < 9){
$this->server->getLogger()->debug("Tried to equip a slot that does not exist (index " . $packet->inventorySlot . ")");
$this->inventory->sendContents($this);
return false;
}
$packet->inventorySlot -= 9; //Get real inventory slot
$item = $this->inventory->getItem($packet->inventorySlot);
if(!$item->equals($packet->item)){
@ -2410,7 +2439,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
case InteractPacket::ACTION_MOUSEOVER:
break; //TODO: handle these
default:
$this->server->getLogger()->debug("Unhandled/unknown interaction type " . $packet->action . "received from ". $this->getName());
$this->server->getLogger()->debug("Unhandled/unknown interaction type " . $packet->action . "received from " . $this->getName());
return false;
}
@ -2418,18 +2448,21 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
public function handleBlockPickRequest(BlockPickRequestPacket $packet) : bool{
$tile = $this->getLevel()->getTile($this->temporalVector->setComponents($packet->tileX, $packet->tileY, $packet->tileZ));
if($tile instanceof Tile){ //TODO: check if the held item matches the target tile
$nbt = $tile->getCleanedNBT();
if($nbt instanceof CompoundTag){
$item = $this->inventory->getItemInHand();
$item->setCustomBlockData($nbt);
$item->setLore(["+(DATA)"]);
$this->inventory->setItemInHand($item);
}
if($this->isCreative()){
$tile = $this->getLevel()->getTile($this->temporalVector->setComponents($packet->tileX, $packet->tileY, $packet->tileZ));
if($tile instanceof Tile){ //TODO: check if the held item matches the target tile
$nbt = $tile->getCleanedNBT();
if($nbt instanceof CompoundTag){
$item = $this->inventory->getItemInHand();
$item->setCustomBlockData($nbt);
$item->setLore(["+(DATA)"]);
$this->inventory->setItemInHand($item);
}
return true;
return true;
}
}
return false;
}
@ -2448,7 +2481,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
if(!$this->canInteract($blockVector->add(0.5, 0.5, 0.5), 13) or $this->isSpectator()){
}elseif($this->isCreative()){
$item = $this->inventory->getItemInHand();
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this, true) === true){
return true;
}
}elseif(!$this->inventory->getItemInHand()->equals($packet->item)){
@ -2457,7 +2490,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$item = $this->inventory->getItemInHand();
$oldItem = clone $item;
//TODO: Implement adventure mode checks
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this)){
if($this->level->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this, true)){
if(!$item->equals($oldItem) or $item->getCount() !== $oldItem->getCount()){
$this->inventory->setItemInHand($item);
$this->inventory->sendHeldItem($this->hasSpawned);
@ -2503,17 +2536,17 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
if($item->getId() === Item::SNOWBALL){
$nbt = new CompoundTag("", [
"Pos" => new ListTag("Pos", [
new ListTag("Pos", [
new DoubleTag("", $this->x),
new DoubleTag("", $this->y + $this->getEyeHeight()),
new DoubleTag("", $this->z)
]),
"Motion" => new ListTag("Motion", [
new ListTag("Motion", [
new DoubleTag("", $aimPos->x),
new DoubleTag("", $aimPos->y),
new DoubleTag("", $aimPos->z)
]),
"Rotation" => new ListTag("Rotation", [
new ListTag("Rotation", [
new FloatTag("", $this->yaw),
new FloatTag("", $this->pitch)
]),
@ -2551,7 +2584,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return true;
}
$packet->eid = $this->id;
$packet->entityRuntimeId = $this->id;
$pos = new Vector3($packet->x, $packet->y, $packet->z);
switch($packet->action){
@ -2571,12 +2604,22 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->level->setBlock($block, new Air());
break;
}
if(!$this->isCreative()){
//TODO: improve this to take stuff like swimming, ladders, enchanted tools into account, fix wrong tool break time calculations for bad tools (pmmp/PocketMine-MP#211)
$breakTime = ceil($target->getBreakTime($this->inventory->getItemInHand()) * 20);
if($breakTime > 0){
$this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_START_BREAK, (int) (65535 / $breakTime));
}
}
$this->lastBreak = microtime(true);
break;
/** @noinspection PhpMissingBreakStatementInspection */
case PlayerActionPacket::ACTION_ABORT_BREAK:
$this->lastBreak = PHP_INT_MAX;
break;
case PlayerActionPacket::ACTION_STOP_BREAK:
$this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_STOP_BREAK);
break;
case PlayerActionPacket::ACTION_RELEASE_ITEM:
if($this->startAction > -1 and $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION)){
@ -2588,21 +2631,22 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
$nbt = new CompoundTag("", [
"Pos" => new ListTag("Pos", [
new ListTag("Pos", [
new DoubleTag("", $this->x),
new DoubleTag("", $this->y + $this->getEyeHeight()),
new DoubleTag("", $this->z)
]),
"Motion" => new ListTag("Motion", [
new ListTag("Motion", [
new DoubleTag("", -sin($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI)),
new DoubleTag("", -sin($this->pitch / 180 * M_PI)),
new DoubleTag("", cos($this->yaw / 180 * M_PI) * cos($this->pitch / 180 * M_PI))
]),
"Rotation" => new ListTag("Rotation", [
new FloatTag("", $this->yaw),
new FloatTag("", $this->pitch)
new ListTag("Rotation", [
//yaw/pitch for arrows taken crosswise, not along the arrow shaft.
new FloatTag("", ($this->yaw > 180 ? 360 : 0) - $this->yaw), //arrow yaw must range from -180 to +180
new FloatTag("", -$this->pitch)
]),
"Fire" => new ShortTag("Fire", $this->isOnFire() ? 45 * 60 : 0)
new ShortTag("Fire", $this->isOnFire() ? 45 * 60 : 0)
]);
$diff = ($this->server->getTick() - $this->startAction);
@ -2651,7 +2695,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
$pk = new EntityEventPacket();
$pk->eid = $this->getId();
$pk->entityRuntimeId = $this->getId();
$pk->event = EntityEventPacket::USE_ITEM;
$this->dataPacket($pk);
$this->server->broadcastPacket($this->getViewers(), $pk);
@ -2691,7 +2735,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->setSneaking(false);
$this->extinguish();
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 400, false);
$this->setDataProperty(self::DATA_AIR, self::DATA_TYPE_SHORT, 400);
$this->deadTicks = 0;
$this->noDamageTicks = 60;
@ -2753,6 +2797,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
case PlayerActionPacket::ACTION_START_GLIDE:
case PlayerActionPacket::ACTION_STOP_GLIDE:
break; //TODO
case PlayerActionPacket::ACTION_CONTINUE_BREAK:
$block = $this->level->getBlock($pos);
$this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_PARTICLE_PUNCH_BLOCK, $block->getId() | ($block->getDamage() << 8) | ($packet->face << 16));
break;
default:
$this->server->getLogger()->debug("Unhandled/unknown player action type " . $packet->action . " from " . $this->getName());
return false;
@ -2764,8 +2812,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return true;
}
public function handlePlayerFall(PlayerFallPacket $packet) : bool{
return false;
public function handleEntityFall(EntityFallPacket $packet) : bool{
return true; //not used
}
public function handleHurtArmor(HurtArmorPacket $packet) : bool{
@ -2803,7 +2851,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
$pk = new AnimatePacket();
$pk->eid = $this->getId();
$pk->entityRuntimeId = $this->getId();
$pk->action = $ev->getAnimationType();
$this->server->broadcastPacket($this->getViewers(), $pk);
@ -3198,11 +3246,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
public function handleSetPlayerGameType(SetPlayerGameTypePacket $packet) : bool{
if($packet->gamemode !== ($this->gamemode & 0x01)){
//GUI gamemode change, set it back to original for now (only possible through client bug or hack with current allowed client permissions)
$pk = new SetPlayerGameTypePacket();
$pk->gamemode = $this->gamemode & 0x01;
$this->dataPacket($pk);
if($packet->gamemode !== $this->gamemode){
//Set this back to default. TODO: handle this properly
$this->sendGamemode();
$this->sendSettings();
}
return true;
@ -3241,7 +3287,14 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$tile = $this->level->getTile($this->temporalVector->setComponents($packet->x, $packet->y, $packet->z));
if($tile instanceof ItemFrame){
$ev = new PlayerInteractEvent($this, $this->inventory->getItemInHand(), $tile->getBlock(), 5 - $tile->getBlock()->getDamage(), PlayerInteractEvent::LEFT_CLICK_BLOCK);
$this->server->getPluginManager()->callEvent($ev);
if($this->isSpectator()){
$ev->setCancelled();
}
if($ev->isCancelled()){
$tile->spawnTo($this);
return true;
}
@ -3264,6 +3317,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return false;
}
public function handleBossEvent(BossEventPacket $packet) : bool{
return false; //TODO
}
public function handleShowCredits(ShowCreditsPacket $packet) : bool{
return false; //TODO: handle resume
}
@ -3278,8 +3335,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
$this->craftingType = 0;
$commandText = $packet->command;
if($packet->args !== null){
foreach($packet->args as $arg){ //command ordering will be an issue
if($packet->inputJson !== null){
foreach($packet->inputJson as $arg){ //command ordering will be an issue
$commandText .= " " . $arg;
}
}
@ -3356,11 +3413,19 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return;
}
//TODO: Remove this hack once InteractPacket spam issue is fixed
if($packet->buffer === "\x21\x04\x00"){
return;
}
$timings = Timings::getReceiveDataPacketTimings($packet);
$timings->startTiming();
$packet->decode();
assert($packet->feof(), "Still " . strlen(substr($packet->buffer, $packet->offset)) . " bytes unread in " . get_class($packet));
if(!$packet->feof()){
$remains = substr($packet->buffer, $packet->offset);
$this->server->getLogger()->debug("Still " . strlen($remains) . " bytes unread in " . $packet->getName() . ": 0x" . bin2hex($remains));
}
$this->server->getPluginManager()->callEvent($ev = new DataPacketReceiveEvent($this, $packet));
if(!$ev->isCancelled() and !$packet->handle($this)){
@ -3439,11 +3504,20 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
public function addTitle(string $title, string $subtitle = "", int $fadeIn = -1, int $stay = -1, int $fadeOut = -1){
$this->setTitleDuration($fadeIn, $stay, $fadeOut);
if($subtitle !== ""){
$this->sendTitleText($subtitle, SetTitlePacket::TYPE_SET_SUBTITLE);
$this->addSubTitle($subtitle);
}
$this->sendTitleText($title, SetTitlePacket::TYPE_SET_TITLE);
}
/**
* Sets the subtitle message, without sending a title.
*
* @param string $subtitle
*/
public function addSubTitle(string $subtitle){
$this->sendTitleText($subtitle, SetTitlePacket::TYPE_SET_SUBTITLE);
}
/**
* Adds small text to the user's screen.
*
@ -3462,6 +3536,15 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->dataPacket($pk);
}
/**
* Resets the title duration settings.
*/
public function resetTitles(){
$pk = new SetTitlePacket();
$pk->type = SetTitlePacket::TYPE_RESET_TITLE;
$this->dataPacket($pk);
}
/**
* Sets the title duration.
*
@ -3496,7 +3579,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
/**
* Sends a direct chat message to a player
*
* @param string|TextContainer $message
* @param TextContainer|string $message
*/
public function sendMessage($message){
if($message instanceof TextContainer){
@ -3566,84 +3649,91 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
*/
final public function close($message = "", $reason = "generic reason", $notify = true){
if($this->connected and !$this->closed){
if($notify and strlen((string) $reason) > 0){
$pk = new DisconnectPacket();
$pk->message = $reason;
$this->directDataPacket($pk);
}
$this->connected = false;
$this->server->getPluginManager()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this);
$this->server->getPluginManager()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this);
if($this->joined){
//TODO: add events for player data saving
$this->save();
$this->server->getPluginManager()->callEvent($ev = new PlayerQuitEvent($this, $message));
if($ev->getQuitMessage() != ""){
$this->server->broadcastMessage($ev->getQuitMessage());
try{
if($notify and strlen((string) $reason) > 0){
$pk = new DisconnectPacket();
$pk->message = $reason;
$this->directDataPacket($pk);
}
}
$this->joined = false;
if($this->isValid()){
foreach($this->usedChunks as $index => $d){
Level::getXZ($index, $chunkX, $chunkZ);
$this->level->unregisterChunkLoader($this, $chunkX, $chunkZ);
foreach($this->level->getChunkEntities($chunkX, $chunkZ) as $entity){
$entity->despawnFrom($this);
$this->connected = false;
$this->server->getPluginManager()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this);
$this->server->getPluginManager()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this);
if($this->joined){
try{
$this->save();
}catch(\Throwable $e){
$this->server->getLogger()->critical("Failed to save player data for " . $this->getName());
$this->server->getLogger()->logException($e);
}
$this->server->getPluginManager()->callEvent($ev = new PlayerQuitEvent($this, $message));
if($ev->getQuitMessage() != ""){
$this->server->broadcastMessage($ev->getQuitMessage());
}
unset($this->usedChunks[$index]);
}
}
$this->usedChunks = [];
$this->loadQueue = [];
$this->joined = false;
foreach($this->server->getOnlinePlayers() as $player){
if(!$player->canSee($this)){
$player->showPlayer($this);
if($this->isValid()){
foreach($this->usedChunks as $index => $d){
Level::getXZ($index, $chunkX, $chunkZ);
$this->level->unregisterChunkLoader($this, $chunkX, $chunkZ);
foreach($this->level->getChunkEntities($chunkX, $chunkZ) as $entity){
$entity->despawnFrom($this);
}
unset($this->usedChunks[$index]);
}
}
}
$this->hiddenPlayers = [];
$this->usedChunks = [];
$this->loadQueue = [];
foreach($this->windowIndex as $window){
$this->removeWindow($window);
}
$this->windows = null;
$this->windowIndex = [];
foreach($this->server->getOnlinePlayers() as $player){
if(!$player->canSee($this)){
$player->showPlayer($this);
}
}
$this->hiddenPlayers = [];
parent::close();
$this->spawned = false;
foreach($this->windowIndex as $window){
$this->removeWindow($window);
}
$this->windows = null;
$this->windowIndex = [];
$this->interface->close($this, $notify ? $reason : "");
parent::close();
$this->spawned = false;
if($this->loggedIn){
$this->interface->close($this, $notify ? $reason : "");
$this->loggedIn = false;
$this->server->getLogger()->info($this->getServer()->getLanguage()->translateString("pocketmine.player.logOut", [
TextFormat::AQUA . $this->getName() . TextFormat::WHITE,
$this->ip,
$this->port,
$this->getServer()->getLanguage()->translateString($reason)
]));
$this->spawnPosition = null;
if($this->perm !== null){
$this->perm->clearPermissions();
$this->perm = null;
}
if($this->inventory !== null){
$this->inventory = null;
$this->currentTransaction = null;
}
}catch(\Throwable $e){
$this->server->getLogger()->logException($e);
}finally{
$this->server->removeOnlinePlayer($this);
$this->server->removePlayer($this);
}
$this->loggedIn = false;
$this->server->getLogger()->info($this->getServer()->getLanguage()->translateString("pocketmine.player.logOut", [
TextFormat::AQUA . $this->getName() . TextFormat::WHITE,
$this->ip,
$this->port,
$this->getServer()->getLanguage()->translateString($reason)
]));
$this->spawnPosition = null;
if($this->perm !== null){
$this->perm->clearPermissions();
$this->perm = null;
}
if($this->inventory !== null){
$this->inventory = null;
$this->currentTransaction = null;
}
$this->server->removePlayer($this);
}
}
@ -3668,10 +3758,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
if($this->hasValidSpawnPosition()){
$this->namedtag["SpawnLevel"] = $this->spawnPosition->getLevel()->getFolderName();
$this->namedtag["SpawnX"] = (int) $this->spawnPosition->x;
$this->namedtag["SpawnY"] = (int) $this->spawnPosition->y;
$this->namedtag["SpawnZ"] = (int) $this->spawnPosition->z;
$this->namedtag->SpawnLevel = new StringTag("SpawnLevel", $this->spawnPosition->getLevel()->getFolderName());
$this->namedtag->SpawnX = new IntTag("SpawnX", (int) $this->spawnPosition->x);
$this->namedtag->SpawnY = new IntTag("SpawnY", (int) $this->spawnPosition->y);
$this->namedtag->SpawnZ = new IntTag("SpawnZ", (int) $this->spawnPosition->z);
}
foreach($this->achievements as $achievement => $status){
@ -3679,7 +3769,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
$this->namedtag["playerGameType"] = $this->gamemode;
$this->namedtag["lastPlayed"] = new LongTag("lastPlayed", floor(microtime(true) * 1000));
$this->namedtag["lastPlayed"] = (int) floor(microtime(true) * 1000);
if($this->username != "" and $this->namedtag instanceof CompoundTag){
$this->server->saveOfflinePlayerData($this->username, $this->namedtag, $async);
@ -3709,12 +3799,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
parent::kill();
$pk = new RespawnPacket();
$pos = $this->getSpawn();
$pk->x = $pos->x;
$pk->y = $pos->y;
$pk->z = $pos->z;
$this->dataPacket($pk);
$this->sendRespawnPacket($this->getSpawn());
}
protected function callDeathEvent(){
@ -3870,7 +3955,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return;
}elseif($this->getLastDamageCause() === $source and $this->spawned){
$pk = new EntityEventPacket();
$pk->eid = $this->id;
$pk->entityRuntimeId = $this->id;
$pk->event = EntityEventPacket::HURT_ANIMATION;
$this->dataPacket($pk);
@ -3885,9 +3970,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pitch = $pitch === null ? $this->pitch : $pitch;
$pk = new MovePlayerPacket();
$pk->eid = $this->getId();
$pk->entityRuntimeId = $this->getId();
$pk->x = $pos->x;
$pk->y = $pos->y + $this->getEyeHeight();
$pk->y = $pos->y + $this->baseOffset;
$pk->z = $pos->z;
$pk->bodyYaw = $yaw;
$pk->pitch = $pitch;
@ -3952,6 +4037,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
$this->sendPosition($this, null, null, MovePlayerPacket::MODE_RESET);
//This only needs to be sent to players who could see us before the teleport.
$this->sendPosition($this, null, null, MovePlayerPacket::MODE_RESET, $this->getViewers());
$this->spawnToAll();
$this->forceMovement = $this->teleportPosition;
$this->teleportPosition = null;

View File

@ -19,7 +19,12 @@
*
*/
declare(strict_types=1);
namespace {
const INT32_MIN = -0x80000000;
const INT32_MAX = 0x7fffffff;
function safe_var_dump(){
static $cnt = 0;
foreach(func_get_args() as $var){
@ -74,7 +79,7 @@ namespace pocketmine {
use raklib\RakLib;
const VERSION = "1.6.2dev";
const API_VERSION = "3.0.0-ALPHA5";
const API_VERSION = "3.0.0-ALPHA6";
const CODENAME = "Unleashed";
/*
@ -84,12 +89,6 @@ namespace pocketmine {
* Enjoy it as much as I did writing it. I don't want to do it again.
*/
if(\Phar::running(true) !== ""){
@define('pocketmine\PATH', \Phar::running(true) . "/");
}else{
@define('pocketmine\PATH', \getcwd() . DIRECTORY_SEPARATOR);
}
if(version_compare("7.0", PHP_VERSION) > 0){
echo "[CRITICAL] You must use PHP >= 7.0" . PHP_EOL;
echo "[CRITICAL] Please use the installer provided on the homepage." . PHP_EOL;
@ -102,6 +101,28 @@ namespace pocketmine {
exit(1);
}
error_reporting(-1);
set_error_handler(function($severity, $message, $file, $line){
if((error_reporting() & $severity)){
throw new \ErrorException($message, 0, $severity, $file, $line);
}else{ //stfu operator
return true;
}
});
if(!extension_loaded("phar")){
echo "[CRITICAL] Unable to find the Phar extension." . PHP_EOL;
echo "[CRITICAL] Please use the installer provided on the homepage." . PHP_EOL;
exit(1);
}
if(\Phar::running(true) !== ""){
define('pocketmine\PATH', \Phar::running(true) . "/");
}else{
define('pocketmine\PATH', realpath(getcwd()) . DIRECTORY_SEPARATOR);
}
if(!class_exists("ClassLoader", false)){
if(!is_file(\pocketmine\PATH . "src/spl/ClassLoader.php")){
echo "[CRITICAL] Unable to find the PocketMine-SPL library." . PHP_EOL;
@ -128,13 +149,12 @@ namespace pocketmine {
set_time_limit(0); //Who set it to 30 seconds?!?!
error_reporting(-1);
ini_set("allow_url_fopen", 1);
ini_set("display_errors", 1);
ini_set("display_startup_errors", 1);
ini_set("allow_url_fopen", '1');
ini_set("display_errors", '1');
ini_set("display_startup_errors", '1');
ini_set("default_charset", "utf-8");
ini_set("memory_limit", -1);
ini_set("memory_limit", '-1');
define('pocketmine\START_TIME', microtime(true));
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-profiler"]);
@ -153,7 +173,7 @@ namespace pocketmine {
//Logger has a dependency on timezone, so we'll set it to UTC until we can get the actual timezone.
date_default_timezone_set("UTC");
$logger = new MainLogger(\pocketmine\DATA . "server.log", \pocketmine\ANSI);
$logger = new MainLogger(\pocketmine\DATA . "server.log");
if(!ini_get("date.timezone")){
if(($timezone = detect_system_timezone()) and date_default_timezone_set($timezone)){
@ -227,7 +247,6 @@ namespace pocketmine {
}
return parse_offset($offset);
break;
case 'linux':
// Ubuntu / Debian.
if(file_exists('/etc/timezone')){
@ -254,7 +273,6 @@ namespace pocketmine {
}
return parse_offset($offset);
break;
case 'mac':
if(is_link('/etc/localtime')){
$filename = readlink('/etc/localtime');
@ -265,10 +283,8 @@ namespace pocketmine {
}
return false;
break;
default:
return false;
break;
}
}
@ -377,7 +393,7 @@ namespace pocketmine {
$args = $trace[$i]["params"];
}
foreach($args as $name => $value){
$params .= (is_object($value) ? get_class($value) . " " . (method_exists($value, "__toString") ? $value->__toString() : "object") : gettype($value) . " " . (is_array($value) ? "Array()" : Utils::printable(@strval($value)))) . ", ";
$params .= (is_object($value) ? get_class($value) . " object" : gettype($value) . " " . (is_array($value) ? "Array()" : Utils::printable(@strval($value)))) . ", ";
}
}
$messages[] = "#$j " . (isset($trace[$i]["file"]) ? cleanPath($trace[$i]["file"]) : "") . "(" . (isset($trace[$i]["line"]) ? $trace[$i]["line"] : "") . "): " . (isset($trace[$i]["class"]) ? $trace[$i]["class"] . (($trace[$i]["type"] === "dynamic" or $trace[$i]["type"] === "->") ? "->" : "::") : "") . $trace[$i]["function"] . "(" . Utils::printable(substr($params, 0, -2)) . ")";
@ -387,139 +403,136 @@ namespace pocketmine {
}
function cleanPath($path){
return rtrim(str_replace(["\\", ".php", "phar://", rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), "/"), rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH), "/")], ["/", "", "", "", ""], $path), "/");
return str_replace(["\\", ".php", "phar://", str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH)], ["/", "", "", "", ""], $path);
}
$errors = 0;
$exitCode = 0;
if(php_sapi_name() !== "cli"){
$logger->critical("You must run PocketMine-MP using the CLI.");
++$errors;
}
do{
$errors = 0;
$pthreads_version = phpversion("pthreads");
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
if(version_compare($pthreads_version, "3.1.5") < 0){
$logger->critical("pthreads >= 3.1.5 is required, while you have $pthreads_version.");
++$errors;
}
if(PHP_INT_SIZE < 8){
$logger->critical("Running PocketMine-MP with 32-bit systems/PHP is no longer supported. Please upgrade to a 64-bit system or use a 64-bit PHP binary.");
$exitCode = 1;
break;
}
if(extension_loaded("pocketmine")){
if(version_compare(phpversion("pocketmine"), "0.0.1") < 0){
$logger->critical("You have the native PocketMine extension, but your version is lower than 0.0.1.");
++$errors;
}elseif(version_compare(phpversion("pocketmine"), "0.0.4") > 0){
$logger->critical("You have the native PocketMine extension, but your version is higher than 0.0.4.");
if(php_sapi_name() !== "cli"){
$logger->critical("You must run PocketMine-MP using the CLI.");
++$errors;
}
}
if(extension_loaded("xdebug")){
$logger->warning("
You are running PocketMine with xdebug enabled. This has a major impact on performance.
");
}
$extensions = [
"curl" => "cURL",
"json" => "JSON",
"mbstring" => "Multibyte String",
"yaml" => "YAML",
"sockets" => "Sockets",
"zip" => "Zip",
"zlib" => "Zlib"
];
foreach($extensions as $ext => $name){
if(!extension_loaded($ext)){
$logger->critical("Unable to find the $name ($ext) extension.");
$pthreads_version = phpversion("pthreads");
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
if(version_compare($pthreads_version, "3.1.5") < 0){
$logger->critical("pthreads >= 3.1.5 is required, while you have $pthreads_version.");
++$errors;
}
}
if($errors > 0){
$logger->critical("Please use the installer provided on the homepage, or recompile PHP again.");
$logger->shutdown();
$logger->join();
exit(1); //Exit with error
}
if(PHP_INT_SIZE < 8){
$logger->warning("Running PocketMine-MP with 32-bit systems/PHP is deprecated. Support for 32-bit may be dropped in the future.");
}
$gitHash = str_repeat("00", 20);
if(file_exists(\pocketmine\PATH . ".git/HEAD")){ //Found Git information!
$ref = trim(file_get_contents(\pocketmine\PATH . ".git/HEAD"));
if(preg_match('/^[0-9a-f]{40}$/i', $ref)){
$gitHash = strtolower($ref);
}elseif(substr($ref, 0, 5) === "ref: "){
$refFile = \pocketmine\PATH . ".git/" . substr($ref, 5);
if(is_file($refFile)){
$gitHash = strtolower(trim(file_get_contents($refFile)));
if(extension_loaded("pocketmine")){
if(version_compare(phpversion("pocketmine"), "0.0.1") < 0){
$logger->critical("You have the native PocketMine extension, but your version is lower than 0.0.1.");
++$errors;
}elseif(version_compare(phpversion("pocketmine"), "0.0.4") > 0){
$logger->critical("You have the native PocketMine extension, but your version is higher than 0.0.4.");
++$errors;
}
}
}
define('pocketmine\GIT_COMMIT', $gitHash);
@define("ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? Binary::BIG_ENDIAN : Binary::LITTLE_ENDIAN));
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
$installer = new SetupWizard();
if(!$installer->run()){
$logger->shutdown();
$logger->join();
exit(-1);
if(extension_loaded("xdebug")){
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running PocketMine with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
}
}
$extensions = [
"curl" => "cURL",
"json" => "JSON",
"mbstring" => "Multibyte String",
"yaml" => "YAML",
"sockets" => "Sockets",
"zip" => "Zip",
"zlib" => "Zlib"
];
if(\Phar::running(true) === ""){
$logger->warning("Non-packaged PocketMine-MP installation detected, do not use on production.");
}
ThreadManager::init();
new Server($autoloader, $logger, \pocketmine\PATH, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
$logger->info("Stopping other threads");
$killer = new ServerKiller(8);
$killer->start();
$erroredThreads = 0;
foreach(ThreadManager::getInstance()->getAll() as $id => $thread){
$logger->debug("Stopping " . $thread->getThreadName() . " thread");
try{
$thread->quit();
$logger->debug($thread->getThreadName() . " thread stopped successfully.");
}catch(\ThreadException $e){
++$erroredThreads;
$logger->debug("Could not stop " . $thread->getThreadName() . " thread: " . $e->getMessage());
foreach($extensions as $ext => $name){
if(!extension_loaded($ext)){
$logger->critical("Unable to find the $name ($ext) extension.");
++$errors;
}
}
}
if($errors > 0){
$logger->critical("Please use the installer provided on the homepage, or recompile PHP again.");
$exitCode = 1;
break;
}
$gitHash = str_repeat("00", 20);
#ifndef COMPILE
if(\Phar::running(true) === ""){
if(Utils::execute("git rev-parse HEAD", $out) === 0){
$gitHash = trim($out);
if(Utils::execute("git diff --quiet") === 1 or Utils::execute("git diff --cached --quiet") === 1){ //Locally-modified
$gitHash .= "-dirty";
}
}
}
#endif
define('pocketmine\GIT_COMMIT', $gitHash);
@define("ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? Binary::BIG_ENDIAN : Binary::LITTLE_ENDIAN));
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors
if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){
$installer = new SetupWizard();
if(!$installer->run()){
$exitCode = -1;
break;
}
}
if(\Phar::running(true) === ""){
$logger->warning("Non-packaged PocketMine-MP installation detected, do not use on production.");
}
ThreadManager::init();
new Server($autoloader, $logger, \pocketmine\PATH, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
$logger->info("Stopping other threads");
$killer = new ServerKiller(8);
$killer->start();
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
$erroredThreads = 0;
foreach(ThreadManager::getInstance()->getAll() as $id => $thread){
$logger->debug("Stopping " . $thread->getThreadName() . " thread");
try{
$thread->quit();
$logger->debug($thread->getThreadName() . " thread stopped successfully.");
}catch(\ThreadException $e){
++$erroredThreads;
$logger->debug("Could not stop " . $thread->getThreadName() . " thread: " . $e->getMessage());
}
}
if($erroredThreads > 0){
if(\pocketmine\DEBUG > 1){
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
}
kill(getmypid());
}
}while(false);
$logger->shutdown();
$logger->join();
echo Terminal::$FORMAT_RESET . PHP_EOL;
if($erroredThreads > 0){
if(\pocketmine\DEBUG > 1){
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
}
kill(getmypid());
}else{
exit(0);
}
exit($exitCode);
}

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine;
/**

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine;
class ThreadManager extends \Volatile{

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine;
/**

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
class AcaciaWoodStairs extends WoodStairs{

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
class ActivatorRail extends Rail{

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -32,8 +34,8 @@ class Air extends Transparent{
protected $id = self::AIR;
protected $meta = 0;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\inventory\AnvilInventory;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\event\TranslationContainer;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -27,8 +29,8 @@ class Bedrock extends Solid{
protected $id = self::BEDROCK;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
class BirchWoodStairs extends WoodStairs{

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
/**
* All Block classes are in here
*/
@ -54,6 +56,8 @@ class Block extends Position implements BlockIds, Metadatable{
public static $hardness = null;
/** @var \SplFixedArray */
public static $transparent = null;
/** @var \SplFixedArray */
public static $diffusesSkyLight = null;
protected $id;
protected $meta = 0;
@ -70,6 +74,7 @@ class Block extends Position implements BlockIds, Metadatable{
self::$solid = new \SplFixedArray(256);
self::$hardness = new \SplFixedArray(256);
self::$transparent = new \SplFixedArray(256);
self::$diffusesSkyLight = new \SplFixedArray(256);
self::$list[self::AIR] = Air::class;
self::$list[self::STONE] = Stone::class;
self::$list[self::GRASS] = Grass::class;
@ -254,31 +259,20 @@ class Block extends Position implements BlockIds, Metadatable{
for($data = 0; $data < 16; ++$data){
self::$fullList[($id << 4) | $data] = new $class($data);
}
self::$solid[$id] = $block->isSolid();
self::$transparent[$id] = $block->isTransparent();
self::$hardness[$id] = $block->getHardness();
self::$light[$id] = $block->getLightLevel();
if($block->isSolid()){
if($block->isTransparent()){
if($block instanceof Liquid or $block instanceof Ice){
self::$lightFilter[$id] = 2;
}else{
self::$lightFilter[$id] = 1;
}
}else{
self::$lightFilter[$id] = 15;
}
}else{
self::$lightFilter[$id] = 1;
}
}else{
self::$lightFilter[$id] = 1;
$block = new UnknownBlock($id);
for($data = 0; $data < 16; ++$data){
self::$fullList[($id << 4) | $data] = new UnknownBlock($id, $data);
}
}
self::$solid[$id] = $block->isSolid();
self::$transparent[$id] = $block->isTransparent();
self::$hardness[$id] = $block->getHardness();
self::$light[$id] = $block->getLightLevel();
self::$lightFilter[$id] = $block->getLightFilter() + 1;
self::$diffusesSkyLight[$id] = $block->diffusesSkyLight();
}
}
}
@ -419,6 +413,29 @@ class Block extends Position implements BlockIds, Metadatable{
return 0;
}
/**
* Returns the amount of light this block will filter out when light passes through this block.
* This value is used in light spread calculation.
*
* @return int 0-15
*/
public function getLightFilter() : int{
return 15;
}
/**
* Returns whether this block will diffuse sky light passing through it vertically.
* Diffusion means that full-strength sky light passing through this block will not be reduced, but will start being filtered below the block.
* Examples of this behaviour include leaves and cobwebs.
*
* Light-diffusing blocks are included by the heightmap.
*
* @return bool
*/
public function diffusesSkyLight() : bool{
return false;
}
/**
* AKA: Block->isPlaceable
*
@ -472,6 +489,14 @@ class Block extends Position implements BlockIds, Metadatable{
return false;
}
/**
* Returns whether entities can climb up this block.
* @return bool
*/
public function canClimb() : bool{
return false;
}
/**
* @return string
*/

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
interface BlockIds{

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
@ -27,8 +29,8 @@ class Bookshelf extends Solid{
protected $id = self::BOOKSHELF;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
@ -27,8 +29,8 @@ class BrewingStand extends Transparent{
protected $id = self::BREWING_STAND_BLOCK;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class Bricks extends Solid{
protected $id = self::BRICKS_BLOCK;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getHardness(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Entity;
@ -84,7 +86,7 @@ class Cactus extends Transparent{
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if($this->getSide(0)->getId() !== self::CACTUS){
if($this->meta == 0x0F){
if($this->meta === 0x0f){
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlock(new Vector3($this->x, $this->y + $y, $this->z));
if($b->getId() === self::AIR){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Effect;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class Clay extends Solid{
protected $id = self::CLAY_BLOCK;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getHardness(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class Coal extends Solid{
protected $id = self::COAL_BLOCK;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getHardness(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class CoalOre extends Solid{
protected $id = self::COAL_ORE;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getHardness(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class Cobblestone extends Solid{
protected $id = self::COBBLESTONE;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getToolType(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Entity;
@ -29,8 +31,8 @@ class Cobweb extends Flowable{
protected $id = self::COBWEB;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function hasEntityCollision(){
@ -57,4 +59,8 @@ class Cobweb extends Flowable{
//TODO: correct drops
return [];
}
public function diffusesSkyLight() : bool{
return true;
}
}

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
class CocoaBlock extends Solid{

View File

@ -19,11 +19,14 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\event\block\BlockGrowEvent;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\Server;
@ -34,8 +37,7 @@ abstract class Crops extends Flowable{
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getId() === self::FARMLAND){
if($block->getSide(Vector3::SIDE_DOWN)->getId() === Block::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, true);
return true;
@ -69,12 +71,12 @@ abstract class Crops extends Flowable{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent() === true){
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== Block::FARMLAND){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if(mt_rand(0, 2) == 1){
if(mt_rand(0, 2) === 1){
if($this->meta < 0x07){
$block = clone $this;
++$block->meta;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -29,8 +31,8 @@ class Dandelion extends Flowable{
protected $id = self::DANDELION;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
class DarkOakWoodStairs extends WoodStairs{

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
class DaylightSensor extends Transparent{

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\level\Level;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
class DetectorRail extends Rail{

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class Diamond extends Solid{
protected $id = self::DIAMOND_BLOCK;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getHardness(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class DiamondOre extends Solid{
protected $id = self::DIAMOND_ORE;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getHardness(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -29,8 +31,8 @@ class Dirt extends Solid{
protected $id = self::DIRT;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function canBeActivated(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class Emerald extends Solid{
protected $id = self::EMERALD_BLOCK;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getHardness(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class EmeraldOre extends Solid{
protected $id = self::EMERALD_ORE;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\inventory\EnchantInventory;
@ -34,8 +36,8 @@ class EnchantingTable extends Transparent{
protected $id = self::ENCHANTING_TABLE;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
@ -27,8 +29,8 @@ class EndStone extends Solid{
protected $id = self::END_STONE;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Entity;
@ -37,23 +39,24 @@ abstract class Fallable extends Solid{
if($type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::AIR or ($down instanceof Liquid)){
$this->level->setBlock($this, Block::get(Block::AIR), true, true);
$fall = Entity::createEntity("FallingSand", $this->getLevel(), new CompoundTag("", [
"Pos" => new ListTag("Pos", [
new ListTag("Pos", [
new DoubleTag("", $this->x + 0.5),
new DoubleTag("", $this->y),
new DoubleTag("", $this->z + 0.5)
]),
"Motion" => new ListTag("Motion", [
new ListTag("Motion", [
new DoubleTag("", 0),
new DoubleTag("", 0),
new DoubleTag("", 0)
]),
"Rotation" => new ListTag("Rotation", [
new ListTag("Rotation", [
new FloatTag("", 0),
new FloatTag("", 0)
]),
"TileID" => new IntTag("TileID", $this->getId()),
"Data" => new ByteTag("Data", $this->getDamage()),
new IntTag("TileID", $this->getId()),
new ByteTag("Data", $this->getDamage()),
]));
$fall->spawnToAll();

View File

@ -19,13 +19,15 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\math\AxisAlignedBB;
class Farmland extends Solid{
class Farmland extends Transparent{
protected $id = self::FARMLAND;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Arrow;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
abstract class Flowable extends Transparent{

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -27,8 +29,8 @@ class Glass extends Transparent{
protected $id = self::GLASS;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -27,8 +29,8 @@ class GlassPane extends Thin{
protected $id = self::GLASS_PANE;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class Glowstone extends Transparent{
protected $id = self::GLOWSTONE_BLOCK;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class Gold extends Solid{
protected $id = self::GOLD_BLOCK;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class GoldOre extends Solid{
protected $id = self::GOLD_ORE;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\event\block\BlockSpreadEvent;
@ -35,8 +37,8 @@ class Grass extends Solid{
protected $id = self::GRASS;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function canBeActivated(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -29,8 +31,8 @@ class GrassPath extends Transparent{
protected $id = self::GRASS_PATH;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class Gravel extends Fallable{
protected $id = self::GRAVEL;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
@ -27,8 +29,8 @@ class HardenedClay extends Solid{
protected $id = self::HARDENED_CLAY;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class Ice extends Transparent{
protected $id = self::ICE;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){
@ -40,6 +42,10 @@ class Ice extends Transparent{
return 0.5;
}
public function getLightFilter() : int{
return 2;
}
public function getToolType(){
return Tool::TYPE_PICKAXE;
}

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class Iron extends Solid{
protected $id = self::IRON_BLOCK;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class IronBars extends Thin{
protected $id = self::IRON_BARS;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class IronOre extends Solid{
protected $id = self::IRON_ORE;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;

View File

@ -2,11 +2,11 @@
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
class JungleWoodStairs extends WoodStairs{

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Entity;
@ -52,6 +54,10 @@ class Ladder extends Transparent{
return 0.4;
}
public function canClimb() : bool{
return true;
}
public function onEntityCollide(Entity $entity){
$entity->resetFallDistance();
$entity->onGround = true;

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class Lapis extends Solid{
protected $id = self::LAPIS_BLOCK;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
@ -28,8 +30,8 @@ class LapisOre extends Solid{
protected $id = self::LAPIS_ORE;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getHardness(){

View File

@ -19,6 +19,8 @@
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Effect;

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