Compare commits

...

295 Commits

Author SHA1 Message Date
c21197ef17 Removed entanglement between chunks and providers. WARNING: BREAKING API CHANGES.
- All entity and tile constructors now require a \pocketmine\level\Level instead of a \pocketmine\level\format\Chunk.
- Chunk->getProvider() and Chunk->setProvider() have been removed.
- Chunk::__construct() has had the $provider parameter removed.
- Chunk->unload() has had the unused $save parameter removed.
- ChunkEvents now take a Level parameter instead of going through the Chunk

API bump to 3.0.0-ALPHA4
2017-02-21 17:08:45 +00:00
0a8826b21f Fixed anti-fly triggered when walking on unknown blocks 2017-02-21 13:43:00 +00:00
dac6c49bce More php7 mess (EndTag Stone, EndTag Portal Frame) 2017-02-21 12:32:50 +00:00
9f7dc32650 Fix some php7 update DoubleTag leftovers 2017-02-21 12:27:27 +00:00
9195375af4 Don't allow these blocks to be washed out, we're only inheriting properties 2017-02-21 11:51:36 +00:00
c6cf3458de Added UnknownBlock class, fixed not-yet-added blocks in imported worlds killing people, close #181 2017-02-21 11:46:44 +00:00
e2cdd9eddc Fixed missing hardness on unimplemented blocks causing gameplay issues 2017-02-21 11:33:06 +00:00
f933107af0 Fix some non-properly-implemented blocks killing people and bad inheritances 2017-02-21 11:17:33 +00:00
408f63f8fa Accuracy again -_- 2017-02-20 19:46:10 +00:00
68998bac48 Update README.md 2017-02-20 16:21:29 +00:00
2ff565afe5 Fix heightmap crashes at the corner of chunks
Stupid unpack() return array indices start at 1, not 0 >_<
2017-02-20 10:28:50 +00:00
20c7e51077 Allow 0.01 of a block diff
Fixes loss of precision when handling player movements causing some position issues.
2017-02-19 17:35:23 +00:00
89216c3bd4 Use parse_ini_file instead of home-grown solution (#366)
* Use parse_ini_file instead of home-grown solution

* Updated PocketMine-Language submodule
2017-02-19 15:53:22 +00:00
834dc343b0 Updated ItemFrameDropItemPacket for >=1.0.3, fix decode errors
Sorry, this DOES NOT FIX creative, blame Mojang. https://bugs.mojang.com/browse/MCPE-20070
2017-02-18 15:09:44 +00:00
91907485b4 Fixed prismarine bad meta crashes 2017-02-18 10:42:25 +00:00
ee523eb5cc Reverted botched fix for #284, close #362
Revert "fixed player data not saving"

This reverts commit b3beb9f71d.

Revert "Call PlayerQuitEvent after unloading chunks, removed some weird code, fixed crash when unloading player level on quit, close #284"

This reverts commit 14a0ff5caa.
2017-02-16 21:04:39 +00:00
f2f51a88e5 Updated PocketMine-Language submodule (again) 2017-02-15 17:55:55 +00:00
abffe1297d Fixed crashes closing entities with unloaded levels 2017-02-15 17:51:41 +00:00
f8b9a13440 Updated PocketMine-Language submodule 2017-02-15 16:06:02 +00:00
5c281c6435 Merged #103 2017-02-15 14:58:41 +00:00
1908ed5812 Fix for incorrect gamemode messages, close #83 (#86)
Shows the correct message ingame but not in the console.
PocketMine doesn't handle the translation for gamemode changes, MCPE
does. No idea why but it requires the second and third parameter....

commands.gamemode.success.other=Set %2$s's game mode to %3$s
commands.gamemode.success.self=Set own game mode to %3$s

To solve the problem we have to change the language files and let
PocketMine-MP translate it.
2017-02-15 14:48:11 +00:00
2d5567d9dd Removed InstallerLang mess, language improvements, updated PocketMine-Language submodule 2017-02-15 14:44:12 +00:00
b3beb9f71d fixed player data not saving 2017-02-14 13:40:58 +00:00
14a0ff5caa Call PlayerQuitEvent after unloading chunks, removed some weird code, fixed crash when unloading player level on quit, close #284 2017-02-14 12:44:31 +00:00
119e458ac8 Removed SQLite3 dependency (no longer used by PocketMine-MP core)
BEFORE anyone yells at me about plugins, having the core demand every extension that a plugin could possibly need is very much sub-optimal. An API for plugin-required extensions will be added in the future.
2017-02-14 11:04:20 +00:00
01a07a0b09 Removed years-old leftovers from old PocketMine 2017-02-13 14:41:30 +00:00
903534572d Shut some inspections up 2017-02-13 14:27:17 +00:00
8a3c30ee7e Moved entity metadata methods out of Binary 2017-02-13 14:05:16 +00:00
91fd99d76a Fixed DestroyBlockParticle 2017-02-12 16:01:23 +00:00
27f2aec160 Fixed wrong docs for Plugin->getPluginFilters() 2017-02-12 12:52:02 +00:00
8f9c52507a Some PhpStorm cleanup 2017-02-12 12:36:02 +00:00
5a12f40074 Only Region file formats are allowed as parameters for RegionLoaders 2017-02-12 12:18:25 +00:00
b89a17ffe2 Added missing attributes encoding to AddEntityPacket 2017-02-12 10:35:35 +00:00
6dc6e32656 Added some very useless functions for easier size changing of entities. (#348) 2017-02-11 21:24:38 +00:00
d430ad50be Fixed wrong temperature and temperature -> rainfall (#347) 2017-02-11 20:15:22 +00:00
06de85fd33 Revert "Fix entities missing in imported leveldb worlds", fixed entities missing after restart in anything OTHER than LevelDB
🤦 I should test this stuff more

This reverts commit ffadc34691.
2017-02-11 19:22:59 +00:00
ffadc34691 Fix entities missing in imported leveldb worlds 2017-02-11 11:15:15 +00:00
f5e39ea9ad Merge branch 'mcpe-1.0.3.0' 2017-02-09 16:36:47 +00:00
595fffc432 Fix chunks not being updated client-side when Level->setChunk() is called (#328)
Fixes half-trees, probably fixes #265
2017-02-09 11:10:25 +00:00
c4d0fdb436 Added clientData field so plugins can access extra data 2017-02-08 21:25:02 +00:00
2a4fb93a92 Updated RakLib, use reliability constants instead of literal values 2017-02-07 11:34:25 +00:00
50bf671c28 Update .travis.yml 2017-02-06 19:32:34 +00:00
4a2b83ab47 Use xargs multi-process to improve lint scanning speed in tests 2017-02-06 18:57:21 +00:00
f332d3647c Fixed lint scan scanning some files twice 2017-02-06 17:21:18 +00:00
0c35c16727 Fix some doc comments 2017-02-06 14:50:05 +00:00
7c8586684e Fixed resource not closed after memory dump (#324) 2017-02-04 18:31:00 +00:00
6999388dd1 Updated DevTools submodule 2017-02-04 13:53:56 +00:00
662652f745 Update SPL submodule 2017-02-03 15:58:35 +00:00
987d492c1c Removed CompatibleClassLoader (not needed anymore) 2017-02-03 12:14:18 +00:00
80920a1673 Remove shutdown after memory dump. (#310) 2017-02-03 10:42:42 +00:00
613226c661 Fix sea lantern lighting doesn't save (#316) 2017-02-02 09:09:54 +00:00
06dd410340 Merge branch 'master' into mcpe-1.0.3.0 2017-02-01 18:15:08 +00:00
cf83143bbd Silence unread buffer assertion on incompatible protocol 2017-02-01 18:13:50 +00:00
28baae8154 Fix RakLib crashing without logging any useful crash information 2017-02-01 17:59:13 +00:00
7701555005 added default port 19132 2017-02-01 15:23:16 +00:00
38937fc4cc Added TransferPacket
TYSM MOJANG
2017-02-01 12:59:01 +00:00
bf6e8db941 Autogenerated data for 1.0.3.0 2017-02-01 10:11:55 +00:00
06c399fa05 Get MainLogger directly, in case translations are needed without a running server 2017-01-31 17:21:21 +00:00
82cf38d46c Installer: No need for force-kills 2017-01-31 12:05:56 +00:00
eb1ec2df05 Removed deprecated network constants 2017-01-31 11:49:55 +00:00
17102058ca Unknown in PlayerFallPacket is fallDistance 2017-01-28 22:03:28 +00:00
f881cea8e0 Remove some unused properties from Player 2017-01-28 17:53:52 +00:00
8beefabbbc Remove useless unset() from 2014 2017-01-28 16:14:37 +00:00
4cca3b866a Enchanted Golden Apples give the eater Absorption 4 (#305) 2017-01-28 12:49:04 +00:00
0535acf211 Update some LevelEvents 2017-01-27 18:21:11 +00:00
478a62e17b Merge branch 'master' into mcpe-1.0 2017-01-27 16:58:53 +00:00
9661d845bb Fix some command stupidity
This is why NOT to write code at 11PM when one is shattered.
2017-01-27 16:57:07 +00:00
69d6d24a38 Removed use of stfu operator 2017-01-27 10:53:49 +00:00
713ee753e4 Fixed wrong git commit hash parsing, fixes #295, closes #297 (#299) 2017-01-27 10:49:54 +00:00
740a8ad436 Lock player position for delayed teleport, and add related assertions 2017-01-26 11:13:35 +00:00
ccef0455ab Fixed CPU/mem leak when teleporting with movement checks disabled, close #231 2017-01-25 19:45:47 +00:00
755f4d232f Merge branch 'master' into mcpe-1.0 2017-01-25 17:37:54 +00:00
09a6776674 Fixed a bug in CrashDump
@xxFlare really?
2017-01-25 17:36:40 +00:00
661f17b6e0 Anti-cheat fixes, settings and API (#287)
* Added options to disable movement checks and anti-instabreak and API methods to control this
* Fixed anti-flight false positives
* Fix flight toggle kick cannot be disabled
* Added PlayerIllegalMoveEvent
2017-01-25 09:40:48 +00:00
77456702e9 Remove some old protocol leftovers 2017-01-24 12:08:25 +00:00
75a38699e2 Fix metadata block coords (signed Y coordinate), close #286 2017-01-23 13:13:29 +00:00
9c36e0cd1c Added crafting data packet cache, reduces on-join lag spikes, close #248 (#269) 2017-01-23 11:03:46 +00:00
21f5be27b6 Added options and API to enable/disable random ticking for specific block IDs 2017-01-23 10:59:27 +00:00
4dd0a13511 Updated DevTools submodule 2017-01-22 16:09:20 +00:00
904c52bb0f Merge branch 'master' into mcpe-1.0 2017-01-22 16:08:34 +00:00
3ab9722a9f Add DevTools as submodule, build DevTools for Travis Test 2017-01-22 16:02:22 +00:00
08ed2cd353 Merge branch 'master' into mcpe-1.0 2017-01-22 11:36:22 +00:00
06f0534d65 Fixed wrong encoding of NBT strings, fixed invisible signs issues 2017-01-22 11:24:55 +00:00
b22232730e Fixed eating golden apple with full hunger, fixed wrong implementation of enchanted golden apple, close #276 2017-01-21 18:25:32 +00:00
50b9034e16 Merge master into mcpe-1.0 2017-01-21 13:43:41 +00:00
8bf8e2e22f Moved crashdumps to their own folder (#275) 2017-01-20 10:52:35 +00:00
52748fcf64 TODO: REVERT - Added a workaround for client text duplication 2017-01-20 10:24:52 +00:00
19572b8c51 Remove multiline separation (unnecessary) 2017-01-20 10:24:52 +00:00
496061ba54 Travis: Build DevTools on the spot 2017-01-20 10:12:16 +00:00
2488d6e957 Updated preprocessor submodule 2017-01-20 10:00:20 +00:00
8ea03524ff Fixed most movement-check false-positives (finally!)
Removed ySize hack, fixes ladders, fixed original autojump and dropdown issues. These were due to a tiny, tiny tiny margin for error when decoding network floats (usually less than 0.000001, but enough to cause issues. Added Binary floating-point decode accuracy option to combat this. Network Vector3s are now rounded to 4 decimal places.
2017-01-20 10:00:20 +00:00
e4aa3d72fe Check for unloaded chunks, fix triple chest bug, fix Chest object leak, close #256
Revert "Fixed double chest tile memory leak on shutdown, close #256 (#261)"

This reverts commit 9869aaa46a.
2017-01-19 15:34:51 +00:00
26fc21d56c API version suffix is now non case sensitive 2017-01-19 10:57:32 +00:00
e4c889ae16 Check if the array contents are already the same, massive performance improvement for Anvil in a lot of cases 2017-01-18 20:04:19 +00:00
7de7593b89 Improved nibble array re-ordering in most cases by checking for common values 2017-01-18 19:51:43 +00:00
162b993e65 Added a hack for multiworld. This is not always reliable! (#263) 2017-01-17 10:28:48 +00:00
cb187be1a1 Remove derp comment 2017-01-16 16:30:52 +00:00
ab943a0462 Fix crashes 2017-01-16 14:50:32 +00:00
2290c33143 Add type-hints to Item::get() (these parameters cannot be null anymore) 2017-01-16 14:08:43 +00:00
9869aaa46a Fixed double chest tile memory leak on shutdown, close #256 (#261) 2017-01-15 19:41:15 +00:00
bcf049a660 Remove obsolete methods from Chunk 2017-01-15 18:03:40 +00:00
0114cb8399 Better vanilla layers support (no meta, MCPE doesn't support it) 2017-01-15 17:26:21 +00:00
b72218ac5b Fixed flat world terrain generation by MCPE 2017-01-15 17:26:21 +00:00
6b9c2b961b Fix invalid timestamp causing W10 Edition to crash, fixes one bug in #254 2017-01-15 17:26:20 +00:00
8ba0b49022 Initial working R/W of 0.16 + 1.0 worlds, highly unstable 2017-01-15 17:26:20 +00:00
74c9ed04a0 LevelDB is loaded? Tell me about it 2017-01-15 17:17:57 +00:00
b28e38ab26 Move some exceptions out of utils into their relevant namespaces, move some Chunk methods to ChunkUtils for I/O, refactor "colour" -> "color" 2017-01-15 11:31:12 +00:00
4577f3ee22 Added config to warn if assertions are enabled and to disable exception throws 2017-01-15 00:38:30 +00:00
3b82a5fddf Fix loop counter and add delay between restarts 2017-01-14 15:28:40 +00:00
2d3b8845fd Add a message for movement reverting 2017-01-14 10:19:53 +00:00
9004417456 Fixed file headers (#255) 2017-01-13 16:57:05 +00:00
946d301bc7 Fix lighting population, fix lighting issues when read by vanilla Minecraft 2017-01-13 11:33:55 +00:00
39c3b16e49 Micro optimization (#252) 2017-01-12 15:38:30 +00:00
3daa2723bf Bump to 7 entries per page (matches MCPE) 2017-01-12 09:42:07 +00:00
085d1a1359 Remove deprecated Utils::getRandomBytes() 2017-01-11 11:53:54 +00:00
3bbf2c245a Shut PhpStorm up 2017-01-11 10:11:13 +00:00
8f797442b3 Merge branch 'master' into mcpe-1.0 2017-01-10 10:55:05 +00:00
57f3f9b4ed Fix setting custom name erases CompoundTag, fixes #244 ...
... even though this bug was introduced AFTER said issue was reported.
Nice work @Muqsit
2017-01-10 08:58:31 +00:00
058468104a Fix setting item custom name does not update inventory
If a NamedTag was already present, it was modifying the object directly
WITHOUT serializing the tag back to raw NBT for sending. This commit
fixes that by always serializing the tag on change.
2017-01-10 00:38:23 +00:00
b566c4e609 Fix Normal generator logic fail 2017-01-09 22:27:35 +00:00
0428894cc6 Merge branch 'master' into mcpe-1.0 2017-01-09 16:04:11 +00:00
41d36e4e7a Fix .gitignore
Ignore the whole folder, stop deleting my damn PhpStorm files
2017-01-09 15:57:38 +00:00
4bf8f00b0f Use MODE_RESET for forceMovement, fixes most teleportation issues 2017-01-09 15:41:05 +00:00
6e87a48100 Revert "Fix a really annoying movement bug on player join", close #231
This reverts commit b16f7e4dd5.
2017-01-09 15:32:10 +00:00
441961b199 Fix players regenerating health from food while dead, fixes issue 2 in #23 2017-01-09 14:10:34 +00:00
92b85e0f15 Fix players regenerating health from food while dead, fixes issue 2 in #23 2017-01-09 14:10:05 +00:00
6fbb9b6083 Check for closed target Levels in Position (#241)
More foolproof
2017-01-09 13:18:28 +00:00
67940ad6ab Added PowerShell start script with loop capability, mainly useful for Win10 users (#240) 2017-01-09 13:16:46 +00:00
0a3fd8737a This is not needed anymore 2017-01-09 11:00:39 +00:00
8902992473 Fix McRegion read corruption errors, close #232
According to the wiki, McRegion heightmap should be ByteArray, not
IntArray. This caused issues with converted worlds with pretty much
every conversion tool. Blame @shoghicp.

IntArray McRegion heightmaps will now be converted to
ByteArray on save.
2017-01-08 21:16:57 +00:00
2e865a3af9 Fix doc comment fail 2017-01-08 19:35:28 +00:00
ed13f7f8e7 Add guideline to test bugs on a clean test server without plugins before reporting 2017-01-08 10:38:53 +00:00
02ddcef24e Fix calls to undefined method Human->getServer() (#234)
* Fixes sendHeldItem to stop crashes when executing.

* Fix server calling for food consuming.
2017-01-07 13:01:26 +00:00
3c9db45cf8 Fix tiles with async chunk sending, TODO: remove this 2017-01-07 10:52:39 +00:00
16e7eaaaa4 Merge branch 'master' into mcpe-1.0 2017-01-07 10:32:47 +00:00
4ace4b9542 Fixed CommandReader hanging on shutdown, close #25 (#171)
Use stream_select to poll stdin status before reading
Add detection for FIFO pipes, rewrite half of the CommandReader (again)
Add timeout for CommandReader to prevent hang in Windows custom consoles (unknown reason)
2017-01-07 10:28:03 +00:00
86dc8c48b9 Fix player burn time in creative 2017-01-06 20:01:21 +00:00
aaf549a469 Docs for Chunk 2017-01-06 17:57:00 +00:00
ad0553fbf8 Bump to API 3.0.0-ALPHA2 - READ DESCRIPTION!
Refactored level\format\generic\GenericChunk -> level\format\Chunk.
Re-added support for async chunk sending
Refactored most Level IO into new namespaces for more organisation
Removed LevelDB loader completely (will be re-added at a later date)
2017-01-06 17:13:45 +00:00
d8908676ac Refactor GenericChunk::fastSerialize() to be non-static, fix some unbelievable bugs, clean up some leftovers 2017-01-05 17:04:02 +00:00
598e7aac8f More PhpStorm inspections, import cleanup 2017-01-04 14:55:11 +00:00
07f18d8f6c Merge branch 'master' into mcpe-1.0 2017-01-04 11:34:39 +00:00
1cb96d24ce Some fixes, thanks PhpStorm 2017-01-04 11:29:24 +00:00
40600be4c1 Better README and contribution guidelines 2017-01-03 22:26:43 +00:00
096836faaa Moved Entity initialization into Entity class 2017-01-03 22:24:41 +00:00
b68df2da5c Remove unused files in preparation for rewrite 2017-01-03 22:24:41 +00:00
e2dc1a3bc6 Some consistency would be nice... fixed inconsistency between block light and sky light, always use Mojang order 2017-01-03 22:24:40 +00:00
8a29e77f5e Add missing byte, fix network sending issues, partly fixes #227 2017-01-03 22:24:40 +00:00
0bd7ea211d Refactored Server::broadcastPacket() to be non-static
Why the hell was this static at all? Seriously Shoghi?
2017-01-03 22:24:40 +00:00
55791e0819 Fix doc formatting from FullChunk -> Chunk mass-replace 2017-01-03 22:24:28 +00:00
69369c8998 Fix dropped items not saving due to missing CompoundTag name, close #223
The NBT library is really badly designed.
2017-01-03 22:24:27 +00:00
c36fc8c027 MobHeads are stackable to 64 2017-01-01 21:54:12 +00:00
7e15c6638a Fix dropped items not saving due to missing CompoundTag name, close #223
The NBT library is really badly designed.
2017-01-01 21:34:07 +00:00
88e36eda59 Stop wasting CPU calling functions 2017-01-01 15:50:13 +00:00
40d1394e3c Reuse empty chunk objects, stop creating new ones 2017-01-01 14:13:06 +00:00
69061ba4ad Removed the need for subchunks to know their Y coordinates 2017-01-01 14:12:58 +00:00
e85d6d134e Fix mob head crashes and drops, fix #221 2017-01-01 01:57:39 +00:00
0e10a149ef Refactor Level::chunkBlockHash() (makes no sense to put it here) 2017-01-01 01:10:10 +00:00
736ec6edac Auto-generated crafting and creative inventory data for 1.0.0.16, do not modify by hand 2016-12-31 16:33:53 +00:00
25b9581254 Make sure tag exists, prevent issues with bad world conversion
Addresses @legoboy0215's comments on #212
2016-12-31 10:24:21 +00:00
b263d81baf Explicit checks for missing tags, fix issues with converted worlds, close #212 2016-12-30 11:18:38 +00:00
0c3780de40 Re-added basic chunk skylight population for GenericChunk (#183) 2016-12-29 11:45:23 +00:00
850afed2c6 Merge branch 'master' into mcpe-1.0 2016-12-29 11:36:14 +00:00
efc6d429f6 Add some 0.16 blocks and items (#210) 2016-12-29 11:35:10 +00:00
b082bec150 Fix instabreak anti-cheat false positive on obsidian broken (#209) 2016-12-28 23:07:57 +00:00
2e1f572356 Fix netherrack and remove redundant override from NetherBrickFence 2016-12-28 23:07:57 +00:00
18ebc64ea0 Rename LevelSoundEventPacket field and add defaults 2016-12-28 23:07:56 +00:00
4f4bdea104 Fix trailing slashes in MOTD breaks server list, close #153 (#154)
Fixes #4083
2016-12-28 23:07:56 +00:00
c556ec84a2 MemoryManager: Fix sprint too less arguments if $from contains %x (#199) 2016-12-28 23:07:55 +00:00
a3a07ca847 Fix instabreak anti-cheat false positive on obsidian broken (#209) 2016-12-28 22:44:42 +00:00
227e1c42ea Fix netherrack and remove redundant override from NetherBrickFence 2016-12-28 22:30:03 +00:00
cb55cefa44 Fix trailing slashes in MOTD breaks server list, close #153 (#154)
Fixes #4083
2016-12-27 21:36:44 +00:00
10c8632417 Fixed effect amplifier overflow crash, close #147 (#191) 2016-12-27 21:30:54 +00:00
942b35ee4c Some metadata flags 2016-12-26 16:59:52 +00:00
440d66bd59 Runtime conversion would be far too slow, remove this redundant option 2016-12-23 20:48:56 +00:00
747aae94ec Refactor PMCustomAnvil -> PMAnvil 2016-12-23 20:38:31 +00:00
6d2a57f83a Prevent attempting to calculate lighting changes below y = 0 (#201) 2016-12-23 20:16:28 +00:00
a63020d6e5 Small performance improvement to nibble array re-ordering
thanks @Intyre
2016-12-23 20:07:55 +00:00
e2bbb76900 Use PMCustomAnvil as the default format for new worlds
mcregion is now "deprecated" due to its lack of suitability (fullchunk style, and no support for 256-high worlds)
2016-12-23 18:15:10 +00:00
f180167955 Add PMCustomAnvil format
Exactly the same as Anvil, but with XZY data ordering. Significantly more performant than Anvil due to no re-ordering necessary.
2016-12-23 18:15:09 +00:00
1eaf7c5431 Workaround for glob() fail, fix worlds not loading properly on some systems, close #197 2016-12-23 18:14:56 +00:00
3672d60bf4 More foolproof region file extension check 2016-12-23 12:40:04 +00:00
7e1557dc94 MemoryManager: Fix sprint too less arguments if $from contains %x (#199) 2016-12-23 12:20:55 +00:00
3848f6f39c Remove Anvil/McRegion circular dependency, more scalable region validity checks 2016-12-23 12:13:32 +00:00
00158d4805 Refactor namespace of Anvil/McRegion 2016-12-23 11:52:55 +00:00
3dcfa7b3ce Fix 32-bit crash and incorrect use of IntTag for Time 2016-12-22 21:03:18 +00:00
acd141e5aa Enable strict types on SubChunk and EmptySubChunk 2016-12-22 18:48:43 +00:00
8ee3723588 Removed Anvil RegionLoader, made mcregion RegionLoader usable for anything 2016-12-22 18:25:18 +00:00
29c27993ad Some mcregion/anvil improvements, add type-hints and enable strict-types 2016-12-22 16:57:03 +00:00
8bdfe0d297 Report CPU and tick usage accurately using averages (#195) 2016-12-22 14:11:46 +00:00
669af6f7b3 Fix a mistake in ItemFrame
thanks @awzaw
2016-12-22 13:47:33 +00:00
f4065dd411 Type-hints, strict-types, doc comments and rearrangement for LevelProviders 2016-12-22 13:16:25 +00:00
a99d7f93d9 Remove redundant return values
why am I still up at 6AM
2016-12-22 06:24:38 +00:00
363b24c663 Fix height limits on subchunks, fixed #196
facepalm
2016-12-22 04:46:28 +00:00
9e938baea0 Merge branch 'master' into mcpe-1.0 2016-12-21 20:27:49 +00:00
fb0c8c2c97 Merge branch 'item-fixes' into mcpe-1.0 2016-12-21 17:15:19 +00:00
772abc609d Fix ItemFrame crash 2016-12-21 17:11:03 +00:00
5feff79875 Fix deepEquals() crash when tag check is specified and only one item has a tag (#188) 2016-12-21 15:25:50 +00:00
7190f6a4ca Fix bow cannot be shot after jumping or sneaking, fix #190 2016-12-21 15:23:03 +00:00
6a066cdf31 Fix deepEquals() crash when tag check is specified and only one item has a tag (#188) 2016-12-21 15:00:00 +00:00
77b3cd71a3 Fixed cannot use items with custom NBT in regular crafting recipe, close #135 2016-12-21 14:55:13 +00:00
5443b10257 Use -1 for anydamage and empty string for null NBT, closes #146 2016-12-21 14:45:34 +00:00
300a3d5ccd Fix default hotbar mapping for W10 2016-12-20 21:19:25 +00:00
17a418f133 fix travis 2016-12-20 16:12:13 +00:00
e2b143a7cf Merge branch 'master' into mcpe-1.0 2016-12-20 13:03:49 +00:00
a1c3ca18ce Fix FlowerPot bugs 2016-12-20 13:01:28 +00:00
8c772fe671 Working item frames 2016-12-20 13:01:28 +00:00
c4d4277a6c Better BlockEntityDataPacket handling 2016-12-20 13:01:27 +00:00
2987c7a80c Remove unnecessary duplication 2016-12-20 12:59:27 +00:00
4063bc4ffb Relocated Server->registerTiles() to Tile::init() 2016-12-20 12:59:27 +00:00
90957cd908 Some tile improvements and added ItemFrame tile 2016-12-20 12:59:26 +00:00
50d59619a6 Remove unnecessary @throws 2016-12-20 12:25:46 +00:00
8db4b7116c Silence this error
Apply STFU operator
2016-12-20 11:08:46 +00:00
4b21e35d6e Fix head rotation issues, thank @jojoe77777 2016-12-20 09:38:47 +00:00
76a1165c0e Fix can't teleport over 128 2016-12-20 09:38:46 +00:00
35fbf78a77 Major API bump due to backwards-incompatible changes (not complete yet) 2016-12-19 21:50:13 +00:00
b86185519a Merge branch 'api-version-suffix' into mcpe-1.0 2016-12-19 21:49:22 +00:00
3433a931c1 Fix load order (no tolerance for mismatches with suffixes) 2016-12-19 19:30:11 +00:00
d9eb767420 Merge branch 'master' into mcpe-1.0 2016-12-19 18:38:13 +00:00
71704228a9 Added support for API alpha/beta/whatever suffixes 2016-12-19 18:08:45 +00:00
a122ea9e75 Merge pull request #161 from pmmp/deprecate-version-constants
Deprecate Minecraft game version constants in the `pocketmine` root namespace
2016-12-19 21:21:38 +08:00
a8694dcbf7 Relocated MINECRAFT_VERSION and MINECRAFT_VERSION_NETWORK to ProtocolInfo and deprecated the originals 2016-12-19 13:16:29 +00:00
1ec83420c8 Show debug messages in Travis test 2016-12-19 02:55:23 +08:00
bb7263beac Fixed script plugins not using first doccomment only 2016-12-17 23:56:43 +08:00
d84f990574 Fix Windows console unresponsive after a few hours, close #104 (#106) 2016-12-17 10:31:10 +00:00
61e8828f94 Fix ladder drops when supporting block is removed 2016-12-16 21:26:54 +00:00
aa8a13c4a3 Fix a bunch of block update bugs due to ancient code 2016-12-16 17:08:38 +00:00
0380c78926 Remove redundant override in Fallable 2016-12-16 16:33:31 +00:00
2930cf80b4 Merge branch 'master' into mcpe-1.0 2016-12-16 10:29:58 +00:00
5ce6c6227f Fix a couple of particle constants
Thanks @thebigsmilexd for information
2016-12-15 23:05:26 +00:00
5dca11dafb Increase ladder bounding box to 3/16, fix kicked for flying when sneaking on ladders (#168) 2016-12-15 16:18:49 +00:00
252d1988dc Merge pull request #166 from pmmp/0.16-isp
0.16 isp (PhpStorm inspections)
2016-12-15 18:45:05 +08:00
bd722bb85f fix misplaced doc 2016-12-15 09:22:51 +00:00
e1253db37c Some more minor changes for autocompletion in IDEs 2016-12-14 21:49:36 +00:00
175dd0efa6 PhpStorm inspections
Fixed some minor bugs and dropped some obsolete code

pocketmine\level\generator namespace is ignored in this commit
2016-12-14 21:49:35 +00:00
146f5a567f Add cases for some unhandled Player Actions and add unknown field to ContainerSetSlotPacket 2016-12-13 11:43:37 +00:00
e790573f2e Fix NBT "getArray()" (#163) 2016-12-12 16:03:05 +00:00
6ea45c5c4a Formatting and doc comments, overall useless commit 2016-12-12 14:25:42 +00:00
544d99f161 Added ability to force literal gamemode checks for Player->isSurvival(), Player->isCreative() and Player->isAdventure() (#155) 2016-12-12 10:07:34 +00:00
42b78cfba2 Some new particle IDs 2016-12-10 15:25:12 +00:00
99e8bcf26b Auto-generated sound constants from 1.0.0.2 2016-12-10 15:10:14 +00:00
6224f0cdf6 Protocol bump for 1.0.0.2 2016-12-10 12:22:28 +00:00
5e6d452678 Fix TNT flashing, add explosion particles and add DATA_FUSE_LENGTH entity data constant 2016-12-09 17:20:07 +00:00
ae6e0773ef Do not perform scheduled updates on still lava/water (#134) 2016-12-09 16:13:39 +00:00
cc9736314e Protocol update for 1.0.0.1
Added PlayerFallPacket
2016-12-08 12:34:31 +00:00
adabd7ef65 Merge branch 'master' into mcpe-1.0 2016-12-06 12:04:42 +00:00
5d16ecc003 Entity Effect Events (#141)
Add EntityEffectEvent class that the EntityEffectAddEvent and
EntityEffectRemoveEvent classes extend. Add event calls to Effect class.
2016-12-06 11:59:49 +00:00
288bf0fe6c Use folder name for saves instead of display name (#150) 2016-12-06 11:58:25 +00:00
e92052c2ab Fix blockhash fail (this would have returned excessive Y coordinates including the bits for X!) 2016-12-05 16:31:47 +00:00
25560a52b0 Remove unused Level field 2016-12-05 16:26:45 +00:00
d625a20934 Remove mess 2016-12-05 10:22:57 +00:00
a0cda3b45a Fixed extra data encoding 2016-12-04 17:46:56 +00:00
d74486a64a Fixed tile spawns 2016-12-04 15:12:45 +00:00
aafe0c4f69 Remove biome colours and fix biome id arrays 2016-12-04 15:12:23 +00:00
4674d34469 Update start.cmd 2016-12-04 14:16:15 +00:00
43b3b41039 Clean up unused files
Clean up unused files
2016-12-04 21:29:33 +08:00
d37afde0dc Disable Travis emails 2016-12-04 10:49:00 +00:00
fecbdc5ff2 Clean up unused files 2016-12-04 10:42:30 +00:00
4d121f7d84 Fix some entity metadata 2016-12-03 22:12:52 +00:00
6a8976c534 New PlayerActionPacket constants 2016-12-03 22:12:52 +00:00
74e31fe712 Fix ./command detection by old plugins (#138)
* Fix ./command detection by old plugins

* plugins might change it 🤦
2016-12-03 20:05:00 +00:00
28c3a882f8 Add new field to UseItemPacket 2016-12-02 18:43:35 +00:00
ebd2830770 Remove nonexistent NBT tags and fix movement issues in PC worlds 2016-12-02 18:06:36 +00:00
2e540300d8 Remove Twitter Link (#136)
Do you guys still have access to the Twitter account? I just noticed that it never got updated. If you still want to use it though, by all means keep this link in here :)
2016-12-02 13:26:32 +00:00
fb74d93e00 Protocol changes for 1.0.0.0 2016-12-02 13:20:52 +00:00
6696b7ed52 Clean up .travis.yml 2016-12-02 12:21:06 +00:00
35b3259053 Fix explosions over 128 do not damage blocks 2016-12-02 00:01:38 +00:00
577dbbce1f Support 256-block build height and fixed world saving 2016-12-01 23:45:12 +00:00
ce289cbe25 Merge branch 'master' into 0.17-chunks 2016-12-01 17:50:12 +00:00
756760a2f0 Fixed clicking on fire to extinguish it (#132) 2016-11-30 15:27:14 +00:00
d6629d6843 More ?? (#131)
* More ??

* fix undefined variable
2016-11-30 10:07:37 +00:00
43a36dba40 Fix op players automatically switching to creative/survival when set to spectator/adventure
Disable GUI gamemode switching, treat it as a cheat.
2016-11-30 09:22:45 +00:00
5025b4aba1 More nibble array re-ordering optimisation 2016-11-29 14:46:49 +00:00
dd01407dd4 Optimized byte re-ordering 2016-11-29 14:46:49 +00:00
d70be232d8 More tweaks 2016-11-29 14:46:48 +00:00
ecabe945e6 Changes for more performance, fixed some crashes and hacked out dodgy light population 2016-11-29 14:46:48 +00:00
2b46794ca2 Optimised nibble array re-ordering (halved loop count) 2016-11-29 14:46:08 +00:00
0be8fa4157 Optimized byte and nibble array re-ordering 2016-11-29 14:44:46 +00:00
b1ce19856f Fix adventure settings not updated for GUI gamemode changes 2016-11-28 11:25:29 +00:00
252afde06f Bump version numbers
Getting as bad as Mojang :O
2016-11-27 21:58:00 +00:00
039d6a488a Fix lighting *facepalm*
http://rmsnews.com/wp-content/uploads/2015/06/clavier-avec-uniquement-ctrl-c-et-ctrl-v.jpg
2016-11-27 21:57:59 +00:00
15f7cfb4f7 Add missing return value, fix blocks vanishing when placed 2016-11-27 21:57:59 +00:00
4c49db6036 New generic in-memory chunk format, fixed 0.17.0.1 chunk loading
Terrible performance, needs profiling. TODO: fix this.
2016-11-27 21:57:59 +00:00
60260a294b Remove chunk order fields 2016-11-27 21:57:59 +00:00
18c0567944 Autogenerated data for 0.17.0.1 (not functional yet) 2016-11-27 21:57:59 +00:00
367fa41161 Remove GUI remnants from start.cmd 2016-11-27 19:29:47 +00:00
439f418b0d Remove debug output 2016-11-27 16:00:54 +00:00
fa5624f87e Check rotation changes. Fix #124, fix #128 2016-11-27 15:58:37 +00:00
c79077cbed Fix MobHead bounding box and properties 2016-11-27 15:50:02 +00:00
995d0847f9 Fix tile derp 2016-11-27 13:06:11 +00:00
aa713c4e4a Added ability to specify tag name for serializing 2016-11-27 12:17:11 +00:00
3b3abab3ad Fix W10 throws away held item on inventory close
This issue will however still crop up if there are actual items in the crafting grid instead of air.
2016-11-27 12:01:09 +00:00
5f5f71cfbe Fix fail due to merge commit 2016-11-26 16:14:29 +00:00
363431dac2 Updated preprocessor submodule 2016-11-26 16:09:43 +00:00
1b543b2c16 Improved varint write performance (#126) 2016-11-26 15:07:27 +00:00
632 changed files with 11414 additions and 9672 deletions

2
.gitignore vendored
View File

@ -11,7 +11,7 @@ server.properties
memoryDump_*/*
# Common IDEs
.idea/*
.idea/
nbproject/*
# Windows image file caches

3
.gitmodules vendored
View File

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

View File

@ -4,15 +4,12 @@ php:
- 7.0
before_script:
- mkdir plugins
- wget -O plugins/DevTools.phar https://github.com/PocketMine/DevTools/releases/download/v1.11.0/DevTools_v1.11.0.phar
- pecl install channel://pecl.php.net/pthreads-3.1.6
- pecl install channel://pecl.php.net/weakref-0.3.2
- pecl install channel://pecl.php.net/weakref-0.3.3
- echo | pecl install channel://pecl.php.net/yaml-2.0.0
script:
- ./tests/lint.sh && ./tests/run.sh
- ./tests/travis.sh
notifications:
email: false
#webhooks: http://n.tkte.ch/h/214/wsNvmG43-ncxUVRrFPwSM-r0

View File

@ -2,69 +2,103 @@
# PocketMine-MP Contribution Guidelines
You must follow these guidelines if you wish to contribute to the PocketMine-MP code base, or participate in issue tracking.
## I have a question
* For questions, please refer to the _#pmmp_ or _#pocketmine_ IRC channel on Freenode. There is a [WebIRC](http://webchat.freenode.net?channels=pmmp,pocketmine&uio=d4) if you do not want to install an IRC client.
* You can ask directly to _[@PocketMine](https://twitter.com/PocketMine)_ in Twitter, but don't expect an immediate reply.
* You may use our [Forum](https://forums.pmmp.io) to ask questions.
* We do not accept questions or support requests in our issue tracker.
## Creating an Issue
* First, use the [Issue Search](https://github.com/pmmp/PocketMine-MP/search?ref=cmdform&type=Issues) to check if anyone has reported it. Check also closed issues, as an issue you think is valid may actually be invalid.
* If an issue has been _fixed_ and closed, create another issue.
* If your issue is related to a plugin, do **not** report here. Contact the plugin's original author instead.
* **Support requests are not bugs.** Issues such as "How do I do this" are not bugs and are closed as soon as a collaborator spots it. They are referred to our Forum to seek assistance. Please refer to the section [I have a quesetion](#i-have-a-question) instead.
* **No generic titles** such as "Question", "Help", "Crash Report" etc.
* If you just got a crash report but you don't understand it, please look for a line starting with `Message`. It summarizes the bug.
* 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 is a support request until the actual bug has been found and therefore the issue is closed.
* 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.
* 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 rqeuest conversation clean and readable.
* If your issue is related to the Pocketmine-MP website, forums, etc., please [talk to a human directly](#i-have-a-question).
- If you are reporting a bug:
- **make sure that you are using the latest supported version** before opening an issue.
- **test it on a clean test server, WITHOUT PLUGINS**, to see if the issue still occurs. If not then it may be a plugin issue. Please also indicate the result of such tests.
- [Search the issue tracker](https://github.com/pmmp/PocketMine-MP/issues?utf8=%E2%9C%93&q=is%3Aissue) to check if anyone has already reported it, to avoid needlessly creating duplicate issues. Make sure you also check closed issues, as an issue you think is valid may already have been resolved.
- If your issue is related to a plugin, **do not report here, contact the plugin's original author** instead.
- **Support requests are not bugs.** Issues such as "How do I do this" are not bugs and will be closed. If you need help, please see [here](README.md#discussion) and do not misuse our issue tracker.
- **No generic titles** such as "Question", "Help", "Crash Report" etc. A good issue report provides a quick summary in the title. If you just got a crash report but you don't understand it, please look for a line starting with `Message`. It summarizes the bug.
- 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.
- 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.
- If your issue is related to the PocketMine-MP website, forums, etc., please [talk to a human directly](README.md#discussion).
## Contributing Code
* Use the [Pull Request](https://github.com/pmmp/PocketMine-MP/pull/new) system, your request will be checked and discussed.
* Create each pull request on a new branch. Do not create a pull request on commits that exist in another pull request.
* Code should use the same syntax as in PocketMine-MP. See below for an example.
* The code must be clear and written in English, comments included.
* Use descriptive commit titles
* **Keep each pull request only contain one feature**. The only exception is when all features in the pull request are related to each other, and share the same core changes.
* **Do not create pull requests that only bump the MCPE version**. If it is ready to be updated, the team will update the values directly. Do not change the MCPE version or protocol version in a pull request, unless you have updated the protocol (all packets) entirely.
- To contribute code to the repository, [fork it on GitHub](https://github.com/pmmp/PocketMine-MP/fork), create a branch on your fork, and make your changes on your fork. You can then make a [pull request](https://github.com/pmmp/PocketMine-MP/pull/new) to the project to compare your branch to ours and propose your changes to our repository. We use the Pull Request system to allow members of the team to review changes before they are merged.
- By proposing a pull request to the project, you agree to your code being distributed within PocketMine-MP under the [LGPL license](LICENSE).
- At PocketMine, **we enforce a very high standard for contributions**. This is because PocketMine-MP and its related projects are used very widely in production. While this might seem like we are being mean at times, **our priority is what is best for PocketMine-MP itself**. We try to ensure that our project's codebase is as clean as possible and ensure that only top-quality material makes it through to PocketMine-MP itself. **If a contribution does not live up to our standards, changes may be requested or the pull request may be closed.**
- **Your pull request will be checked and discussed in due time.** Since the team is scattered all around the world, your PR may not receive any attention for some time.
- **Avoid using GitHub Web Editor**. The web editor lacks most useful GIT features and **should only be used for very minor changes**. It is immediately clear if the web editor has been used, and if so the PR is more likely to be rejected. If you want to make serious contributions, **please learn how to use [GIT version control](https://git-scm.com/)**.
- **Do not copy-paste code**. There are potential license issues implicit with copy-pasting, and copy-paste usually indicates a lack of understanding of the actual code. Copy-pasted code is obvious a mile off and **any PR like this is likely to be closed**. If you want to use somebody else's code from a Git repository, **use [GIT's cherry-pick feature](https://git-scm.com/docs/git-cherry-pick)** to cherry-pick the commit. **Cherry-picking is the politer way to copy somebody's changes** and retains all the original accreditation, so there is no need for copy-pasted commits with descriptions like `Some code, thanks @exampleperson`.
- In addition to the above, **make sure you can explain your changes**. If you can't provide a good explanation of changes, your PR may be rejected.
- **Create a new branch for each pull request.** Do not create a pull request with commits that exist in another pull request.
- **Code should use the same style as in PocketMine-MP.** See [below](#code-syntax) for an example.
- **The code must be clear** and written in English, comments included.
- **Use descriptive commit titles.** You can see an example [here](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
- **Try to stick to one change per commit.** This ensures that if you create a PR with several changes, we can decide which ones we wish to include and which ones not to include.
- **It is inadvisable to create pull requests with large commits** unless this has been discussed with the team beforehand. Large pull requests are difficult to review, and such pull requests may end up being closed. The only exception is when all features in the pull request are related to each other, and share the same core changes.
- **You may be asked to rebase your pull request** if the branch becomes outdated and/or if possibly conflicting changes are made to the target branch. To see how to do this, read [this page](https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request).
**Thanks for contributing to PocketMine-MP!**
### Code Syntax
It is mainly [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md) with a few exceptions.
* Opening braces MUST go on the same line, and MUST NOT have spaces before.
* `else if` MUST be written as `elseif`. _(It is in PSR-2, but using a SHOULD)_
* Control structure keywords or opening braces MUST NOT have one space before or after them.
* Code MUST use tabs for indenting.
* Long arrays MAY be split across multiple lines, where each subsequent line is indented once.
* Files MUST use only the `<?php` tag.
* Files MUST NOT have an ending `?>` tag.
* Code MUST use namespaces.
* Strings SHOULD use the double quote `"` except when the single quote is required.
- Opening braces MUST go on the same line, and MUST NOT have spaces before.
- `else if` MUST be written as `elseif`. _(It is in PSR-2, but using a SHOULD)_
- Control structure keywords or opening braces MUST NOT have one space before or after them.
- Code MUST use tabs for indenting.
- Long arrays MAY be split across multiple lines, where each subsequent line is indented once.
- Files MUST use only the `<?php` tag.
- Files MUST NOT have an ending `?>` tag.
- Code MUST use namespaces.
- Strings SHOULD use the double quote `"` except when the single quote is required.
- All code SHOULD have parameter and type declarations where possible.
- Strict types SHOULD be enabled on new files where it is sensible to do so.
```php
<?php
declare(strict_types = 1);
namespace pocketmine\example;
class ExampleClass{
const EXAMPLE_CLASS_CONSTANT = 1;
public $examplePublicVariable = "defaultValue";
private $examplePrivateVariable;
/**
* Creates an instance of ExampleClass
*
* @param string $firstArgument the first argument
* @param string|null $secondArgument default null
*/
public function __construct($firstArgument, &$secondArgument = null){
if($firstArgument === "exampleValue"){ //Remember to use === instead == when possible
public function __construct(string $firstArgument, &$secondArgument = null){
if($firstArgument === "exampleValue"){ //Remember to use === instead of == when possible
//do things
}elseif($firstArgument === "otherValue"){
$secondArgument = function(){
@ -76,10 +110,14 @@ class ExampleClass{
4 => "value5",
5 => "value6",
];
}
};
}
}
public function doStuff(string $stuff) : string{
return $stuff;
}
}
```
@ -94,78 +132,3 @@ class ExampleClass{
* An RFC will be rejected if less than 50% + 1 (simple majority) has voted Yes.
* If the RFC is approved, Team Members have the final word on its implementation or rejection.
* RFCs with complex voting options will specify the vote percentage or other details.
## Bug Tracking for Collaborators
### Labels
To provide a concise bug tracking environment, prevent the issue tracker from over flowing and to keep support requests out of the bug tracker, PocketMine-MP uses a label scheme a bit different from the default GitHub Issues labels.
Labels are used to identify the type and status of issues and pull requests.
#### Categories
Multiple category labels may be applied to a single issue (but try to keep this to a minimum and do not overuse category labels).
These labels may be applied to issues with bugs related to these, or pull requests that alter the behaviour of these or fix an issue with the same label applied.
- `Category: Core` - Related to PocketMine-MP's core functionality, but not gameplay or API.
- `Category: Gameplay` - Related to gameplay.
- `Category: API` - Related to plugin API.
- `Category: Client` - Related to client functionality or behaviour. This label may be applied to issues reporting client-related bugs, or PRs related to the client such as a protocol update. There are several sub-labels to account for the differences between supported clients.
- `all`: Related to all versions of the client.
- `W10`: Related only to Windows 10 Edition Beta.
- `PE`: Related only to the Pocket Edition
- `beta`: Related only to a beta version of the game.
- `other`: Related only to an uncommon PE-compatible version of the client, such as VR Edition.
- `Category: PHP` - Applied to issues caused by the PHP interpreter or its extensions.
- `Category: Other` - Applied to issues which cannot be categorized with any of the above labels.
#### Pull Requests
Pull Request labels are prefixed by `PR:`. Only one label may be applied for a Pull Request.
- `PR: Bug Fix` - The Pull Request fixes a bug.
- `PR: Contribution` - The Pull Request contributes new features or improvements, but does not fix a bug, nor controversial enough to be an RFC.
- `PR: RFC` - Request for Comments. Refer to [RFC and Voting](#rfc-and-voting).
#### Status
Status labels show the status of the issue. Multiple status labels may be applied.
*Issues*
- `Status: Unconfirmed` - reported issues that have yet to be reproduced by a developer successfully.
- `Status: Reproduced` - a bug that has been reproduced by a developer, or that multiple people are reporting the same issue and symptoms in which case it is automatically assumed that the bug has been reproduced in different environments.
- `Status: Debugged` - the cause of the bug has been found, but has not yet been fixed.
- `Status: Resolved` - applied to *valid* issues which have been fixed. *This label may only be applied to a closed issue.*
*Pull requests*
- `Status: Insufficiently tested` - applied for pull requests that have not undergone tests strict enough.
#### Resolution
Resolution labels show the resolution of an issue or pull request. These labels may only be applied to closed issues.
- `Resolution: Invalid` - Applied to support request issues or issues not related to PocketMine.
- `Resolution: Duplicate` - Applied to issues reporting the same problems as another issue.
- `Resolution: Fixed` - Applied to an issue reporting a bug which has been fixed.
- `Resolution: Works As Intended` - Applied to issues reporting false bugs which work the way they are intended to.
- `Resolution: Won't Fix` - Applied to issues reporting bugs which will not be fixed, for example if the bug is beneficial.
- `Resolution: Obsolete` - Applied to pull requests which are rendered unnecessary by other changes, such as another, similar pull request being merged.
#### Miscellaneous
- `Enhancement` - Applied to issues with viable feature requests or TODO lists.
- `High priority` - Applied to issues or PRs related to critical bugs.
### Closing Issues
To keep the bug tracker clear of non-related issues and to prevent it from overflowing, **issues must be closed as soon as possible** (This may sound unethical, but it is MUCH better than having the BUG TRACKER filled with SUPPORT REQUESTS and "I NEED HELP").
If an issue does not conform to the "Creating an Issue" guidelines above, the issue should be closed.
<!--
### Milestones
PocketMine-MP uses GitHub Milestones to set a goal for a new release. A milestone is set on the following occasions.
- A new Beta release
- A new Stable release
A milestone must use the following format:
```
<version_number> [release_title][release_version]
```
For example:
```
1.6.1b1
```
-->

View File

@ -1,6 +1,45 @@
# ![PocketMine-MP](http://cdn.pocketmine.net/img/PocketMine-MP-h.png)
# [![PocketMine-MP](http://cdn.pocketmine.net/img/PocketMine-MP-h.png)](https://pmmp.io)
__A highly customisable, open source server software for Minecraft: Pocket Edition written in PHP__
[![Build Status](https://travis-ci.org/pmmp/PocketMine-MP.svg?branch=master)](https://travis-ci.org/pmmp/PocketMine-MP)
### Setup, help & support, FAQs
Head over to the [documentation site](http://pmmp.readthedocs.org/).
If you don't find what you're looking for there, [talk to a human](#discussion). Please do not use our issue tracker for support requests.
### Discussion
- [Forums](https://forums.pmmp.io/)
- [#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/), [Poggit](https://poggit.pmmp.io) or just search GitHub.
### For developers
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP%20Docs/doxygen/) - Doxygen documentation generated from development
* [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - A development tools plugin for creating plugins.
### Can I contribute?
Yes you can! Contributions are welcomed provided that they comply with our [Contributing Guidelines](CONTRIBUTING.md). Please ensure you read the relevant sections of the guidelines carefully before making a Pull Request or opening an Issue.
<!-- TODO uncomment this when Jenkins is fixed
### Where can I get the latest .phar?
Head over to our [official Jenkins server](https://jenkins.pmmp.io/)
-->
## Third-party Libraries/Protocols Used
* __[PHP Sockets](http://php.net/manual/en/book.sockets.php)__
* __[PHP mbstring](http://php.net/manual/en/book.mbstring.php)__
* __[PHP BCMath](http://php.net/manual/en/book.bc.php)__
* __[PHP pthreads](http://pthreads.org/)__ by _[krakjoe](https://github.com/krakjoe)_: Threading for PHP - Share Nothing, Do Everything.
* __[PHP YAML](https://code.google.com/p/php-yaml/)__ by _Bryan Davis_: The Yaml PHP Extension provides a wrapper to the LibYAML library.
* __[LibYAML](http://pyyaml.org/wiki/LibYAML)__ by _Kirill Simonov_: A YAML 1.1 parser and emitter written in C.
* __[cURL](http://curl.haxx.se/)__: cURL is a command line tool for transferring data with URL syntax
* __[Zlib](http://www.zlib.net/)__: A Massively Spiffy Yet Delicately Unobtrusive Compression Library
* __[Source RCON Protocol](https://developer.valvesoftware.com/wiki/Source_RCON_Protocol)__
* __[UT3 Query Protocol](http://wiki.unrealadmin.org/UT3_query_protocol)__
## Licensing information
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
@ -15,43 +54,4 @@
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
__PocketMine-MP is a free, open-source software that creates Minecraft: Pocket Edition servers and allows extending its functionalities__
### [Homepage](https://pmmp.io/)
### [Forums](https://forums.pmmp.io/)
### [Documentation](http://pmmp.readthedocs.org/)
### [Plugin Repository](http://plugins.pocketmine.net/)
<!--## [FAQ: Frequently Asked Questions](https://github.com/PocketMine/PocketMine-MP/wiki/Frequently-Asked-Questions)-->
### [Official Jenkins server](https://jenkins.pmmp.io/)
### API Documentation
* [Official Doxygen-generated documentation](http://docs.pocketmine.net/)
* [Latest Doxygen generated from development](https://jenkins.pmmp.io/job/PocketMine-MP%20Docs/doxygen/)
### [Twitter @PocketMine](https://twitter.com/PocketMine)
### IRC Chat #pmmp (or #pocketmine) @ irc.freenode.net
[#pmmp + #pocketmine channel WebIRC](http://webchat.freenode.net/?channels=pmmp,pocketmine)
### Want to contribute?
* Check the [Contributing Guidelines](CONTRIBUTING.md)
## Third-party Libraries/Protocols Used
* __[PHP Sockets](http://php.net/manual/en/book.sockets.php)__
* __[PHP mbstring](http://php.net/manual/en/book.mbstring.php)__
* __[PHP SQLite3](http://php.net/manual/en/book.sqlite3.php)__
* __[PHP BCMath](http://php.net/manual/en/book.bc.php)__
* __[PHP pthreads](http://pthreads.org/)__ by _[krakjoe](https://github.com/krakjoe)_: Threading for PHP - Share Nothing, Do Everything.
* __[PHP YAML](https://code.google.com/p/php-yaml/)__ by _Bryan Davis_: The Yaml PHP Extension provides a wrapper to the LibYAML library.
* __[LibYAML](http://pyyaml.org/wiki/LibYAML)__ by _Kirill Simonov_: A YAML 1.1 parser and emitter written in C.
* __[cURL](http://curl.haxx.se/)__: cURL is a command line tool for transferring data with URL syntax
* __[Zlib](http://www.zlib.net/)__: A Massively Spiffy Yet Delicately Unobtrusive Compression Library
* __[Source RCON Protocol](https://developer.valvesoftware.com/wiki/Source_RCON_Protocol)__
* __[UT3 Query Protocol](http://wiki.unrealadmin.org/UT3_query_protocol)__
pmmp/PocketMine are not affiliated with Mojang. All brands and trademarks belong to their respective owners. PocketMine-MP is not a Mojang-approved software, nor is it associated with Mojang.

View File

@ -41,7 +41,10 @@ class CrashDump{
public function __construct(Server $server){
$this->time = time();
$this->server = $server;
$this->path = $this->server->getDataPath() . "CrashDump_" . date("D_M_j-H.i.s-T_Y", $this->time) . ".log";
if(!is_dir($this->server->getDataPath() . "crashdumps")){
mkdir($this->server->getDataPath() . "crashdumps");
}
$this->path = $this->server->getDataPath() . "crashdumps/" . date("D_M_j-H.i.s-T_Y", $this->time) . ".log";
$this->fp = @fopen($this->path, "wb");
if(!is_resource($this->fp)){
throw new \RuntimeException("Could not create Crash Dump");
@ -160,7 +163,7 @@ class CrashDump{
];
$error["fullFile"] = $error["file"];
$error["file"] = cleanPath($error["file"]);
$error["type"] = isset($errorConversion[$error["type"]]) ? $errorConversion[$error["type"]] : $error["type"];
$error["type"] = $errorConversion[$error["type"]] ?? $error["type"];
if(($pos = strpos($error["message"], "\n")) !== false){
$error["message"] = substr($error["message"], 0, $pos);
}

View File

@ -285,6 +285,8 @@ class MemoryManager{
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));
@ -292,8 +294,6 @@ class MemoryManager{
echo "[Dump] Finished!\n";
gc_enable();
$this->server->forceShutdown();
}
private function continueDump($from, &$data, &$objects, &$refCounts, $recursion, $maxNesting, $maxStringSize){
@ -323,7 +323,7 @@ class MemoryManager{
$this->continueDump($value, $data[$key], $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
}
}elseif(is_string($from)){
$data = sprintf("(string) len(%d) " . substr(Utils::printable($from), 0, $maxStringSize), strlen($from));
$data = "(string) len(". strlen($from) .") " . substr(Utils::printable($from), 0, $maxStringSize);
}elseif(is_resource($from)){
$data = "(resource) " . print_r($from, true);
}else{

View File

@ -32,7 +32,6 @@ use pocketmine\entity\Human;
use pocketmine\entity\Item as DroppedItem;
use pocketmine\entity\Living;
use pocketmine\entity\Projectile;
use pocketmine\event\block\SignChangeEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
@ -42,6 +41,7 @@ use pocketmine\event\inventory\CraftItemEvent;
use pocketmine\event\inventory\InventoryCloseEvent;
use pocketmine\event\inventory\InventoryPickupArrowEvent;
use pocketmine\event\inventory\InventoryPickupItemEvent;
use pocketmine\event\player\cheat\PlayerIllegalMoveEvent;
use pocketmine\event\player\PlayerAchievementAwardedEvent;
use pocketmine\event\player\PlayerAnimationEvent;
use pocketmine\event\player\PlayerBedEnterEvent;
@ -81,7 +81,7 @@ use pocketmine\inventory\ShapelessRecipe;
use pocketmine\inventory\SimpleTransactionGroup;
use pocketmine\item\Item;
use pocketmine\level\ChunkLoader;
use pocketmine\level\format\FullChunk;
use pocketmine\level\format\Chunk;
use pocketmine\level\Level;
use pocketmine\level\Location;
use pocketmine\level\Position;
@ -119,7 +119,6 @@ use pocketmine\network\protocol\PlayerActionPacket;
use pocketmine\network\protocol\PlayStatusPacket;
use pocketmine\network\protocol\ResourcePacksInfoPacket;
use pocketmine\network\protocol\RespawnPacket;
use pocketmine\network\protocol\SetDifficultyPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\network\protocol\SetHealthPacket;
use pocketmine\network\protocol\SetPlayerGameTypePacket;
@ -134,10 +133,8 @@ use pocketmine\network\SourceInterface;
use pocketmine\permission\PermissibleBase;
use pocketmine\permission\PermissionAttachment;
use pocketmine\plugin\Plugin;
use pocketmine\tile\Sign;
use pocketmine\tile\ItemFrame;
use pocketmine\tile\Spawnable;
use pocketmine\tile\Tile;
use pocketmine\utils\Binary;
use pocketmine\utils\TextFormat;
use pocketmine\utils\UUID;
@ -174,27 +171,20 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
protected $messageCounter = 2;
protected $sendIndex = 0;
private $clientSecret;
/** @var Vector3 */
public $speed = null;
public $blocked = false;
public $achievements = [];
public $lastCorrect;
/** @var SimpleTransactionGroup */
protected $currentTransaction = null;
public $craftingType = 0; //0 = 2x2 crafting, 1 = 3x3 crafting, 2 = stonecutter
protected $isCrafting = false;
public $creationTime = 0;
protected $randomClientId;
protected $lastMovement = 0;
/** @var Vector3 */
protected $forceMovement = null;
/** @var Vector3 */
@ -240,6 +230,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
protected $allowFlight = false;
protected $flying = false;
protected $allowMovementCheats = false;
protected $allowInstaBreak = false;
private $needACK = [];
private $batchedPackets = [];
@ -337,6 +330,22 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return $this->autoJump;
}
public function allowMovementCheats() : bool{
return $this->allowMovementCheats;
}
public function setAllowMovementCheats(bool $value = false){
$this->allowMovementCheats = $value;
}
public function allowInstaBreak() : bool{
return $this->allowInstaBreak;
}
public function setAllowInstaBreak(bool $value = false){
$this->allowInstaBreak = $value;
}
/**
* @param Player $player
*/
@ -507,20 +516,18 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
public function sendCommandData(){
$pk = new AvailableCommandsPacket();
$data = new \stdClass();
$count = 0;
foreach($this->server->getCommandMap()->getCommands() as $command){
//TODO: fix command permission checks on join
/*if(!$command->testPermissionSilent($this)){
continue;
}*/
++$count;
$data->{$command->getName()}->versions[0] = $command->generateCustomCommandData($this);
if(($cmdData = $command->generateCustomCommandData($this)) !== null){
++$count;
$data->{$command->getName()}->versions[0] = $cmdData;
}
}
if($count > 0){
//TODO: structure checking
$pk = new AvailableCommandsPacket();
$pk->commands = json_encode($data);
$this->dataPacket($pk);
}
@ -530,7 +537,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
* @param SourceInterface $interface
* @param null $clientID
* @param string $ip
* @param integer $port
* @param int $port
*/
public function __construct(SourceInterface $interface, $clientID, $ip, $port){
$this->interface = $interface;
@ -556,6 +563,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->rawUUID = null;
$this->creationTime = microtime(true);
$this->allowMovementCheats = (bool) $this->server->getProperty("player.anti-cheat.allow-movement-cheats", false);
$this->allowInstaBreak = (bool) $this->server->getProperty("player.anti-cheat.allow-instabreak", false);
}
/**
@ -666,12 +676,21 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$level = $level === null ? $this->level : $level;
$index = Level::chunkHash($x, $z);
if(isset($this->usedChunks[$index])){
foreach($level->getChunkEntities($x, $z) as $entity){
$chunk = $level->getChunk($x, $z);
foreach($chunk->getEntities() as $entity){
if($entity !== $this){
$entity->despawnFrom($this);
}
}
if($level !== $this->level){
$pk = new FullChunkDataPacket();
$pk->chunkX = $x;
$pk->chunkZ = $z;
$pk->data = chr($chunk->getSubChunkSendCount());
$this->dataPacket($pk);
}
unset($this->usedChunks[$index]);
}
$level->unregisterChunkLoader($this, $x, $z);
@ -698,7 +717,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return $this->spawnPosition instanceof WeakPosition and $this->spawnPosition->isValid();
}
public function sendChunk($x, $z, $payload, $ordering = FullChunkDataPacket::ORDER_COLUMNS){
public function sendChunk($x, $z, $payload){
if($this->connected === false){
return;
}
@ -712,7 +731,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk = new FullChunkDataPacket();
$pk->chunkX = $x;
$pk->chunkZ = $z;
$pk->order = $ordering;
$pk->data = $payload;
$this->batchDataPacket($pk);
}
@ -1079,8 +1097,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
*/
public function awardAchievement($achievementId){
if(isset(Achievement::$list[$achievementId]) and !$this->hasAchievement($achievementId)){
foreach(Achievement::$list[$achievementId]["requires"] as $requerimentId){
if(!$this->hasAchievement($requerimentId)){
foreach(Achievement::$list[$achievementId]["requires"] as $requirementId){
if(!$this->hasAchievement($requirementId)){
return false;
}
}
@ -1154,11 +1172,12 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk = new SetPlayerGameTypePacket();
$pk->gamemode = $this->gamemode & 0x01;
$this->dataPacket($pk);
$this->sendSettings();
}else{
Command::broadcastCommandMessage($this, new TranslationContainer("commands.gamemode.success.self", [Server::getGamemodeString($gm)]));
}
$this->sendSettings();
$this->inventory->sendContents($this);
$this->inventory->sendContents($this->getViewers());
$this->inventory->sendHeldItem($this->hasSpawned);
@ -1185,28 +1204,62 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
/**
* WARNING: This method does NOT return literal gamemode is survival, it will also return true for adventure mode players.
* NOTE: Because Survival and Adventure Mode share some similar behaviour, this method will also return true if the player is
* in Adventure Mode. Supply the $literal parameter as true to force a literal Survival Mode check.
*
* @param bool $literal whether a literal check should be performed
*
* @return bool
*/
public function isSurvival() : bool{
return ($this->gamemode & 0x01) === 0;
public function isSurvival(bool $literal = false) : bool{
if($literal){
return $this->gamemode === Player::SURVIVAL;
}else{
return ($this->gamemode & 0x01) === 0;
}
}
/**
* WARNING: This method does NOT return literal gamemode is creative, it will also return true for spectator mode players.
* NOTE: Because Creative and Spectator Mode share some similar behaviour, this method will also return true if the player is
* in Spectator Mode. Supply the $literal parameter as true to force a literal Creative Mode check.
*
* @param bool $literal whether a literal check should be performed
*
* @return bool
*/
public function isCreative() : bool{
return ($this->gamemode & 0x01) === 1;
public function isCreative(bool $literal = false) : bool{
if($literal){
return $this->gamemode === Player::CREATIVE;
}else{
return ($this->gamemode & 0x01) === 1;
}
}
/**
* WARNING: This method does NOT return literal gamemode is adventure, it will also return true for spectator mode players.
* NOTE: Because Adventure and Spectator Mode share some similar behaviour, this method will also return true if the player is
* in Spectator Mode. Supply the $literal parameter as true to force a literal Adventure Mode check.
*
* @param bool $literal whether a literal check should be performed
*
* @return bool
*/
public function isAdventure() : bool{
return ($this->gamemode & 0x02) > 0;
public function isAdventure(bool $literal = false) : bool{
if($literal){
return $this->gamemode === Player::ADVENTURE;
}else{
return ($this->gamemode & 0x02) > 0;
}
}
/**
* @return bool
*/
public function isSpectator() : bool{
return $this->gamemode === 3;
return $this->gamemode === Player::SPECTATOR;
}
public function isFireProof() : bool{
return $this->isCreative();
}
public function getDrops(){
@ -1259,7 +1312,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk = new TakeItemEntityPacket();
$pk->eid = $this->getId();
$pk->target = $entity->getId();
Server::broadcastPacket($entity->getViewers(), $pk);
$this->server->broadcastPacket($entity->getViewers(), $pk);
$pk = new TakeItemEntityPacket();
$pk->eid = 0;
@ -1294,7 +1347,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk = new TakeItemEntityPacket();
$pk->eid = $this->getId();
$pk->target = $entity->getId();
Server::broadcastPacket($entity->getViewers(), $pk);
$this->server->broadcastPacket($entity->getViewers(), $pk);
$pk = new TakeItemEntityPacket();
$pk->eid = 0;
@ -1310,7 +1363,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
protected function processMovement($tickDiff){
if(!$this->isAlive() or !$this->spawned or $this->newPosition === null or $this->teleportPosition !== null){
if(!$this->isAlive() or !$this->spawned or $this->newPosition === null or $this->teleportPosition !== null or $this->isSleeping()){
return;
}
@ -1319,7 +1372,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$revert = false;
if(($distanceSquared / ($tickDiff ** 2)) > 100){
if(($distanceSquared / ($tickDiff ** 2)) > 100 and !$this->allowMovementCheats){
$this->server->getLogger()->warning($this->getName() . " moved too fast, reverting movement");
$revert = true;
}else{
if($this->chunk === null or !$this->chunk->isGenerated()){
@ -1347,19 +1401,17 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$diffY = $this->y - $newPos->y;
$diffZ = $this->z - $newPos->z;
$yS = 0.5 + $this->ySize;
if($diffY >= -$yS or $diffY <= $yS){
$diffY = 0;
}
$diff = ($diffX ** 2 + $diffY ** 2 + $diffZ ** 2) / ($tickDiff ** 2);
if($this->isSurvival()){
if(!$revert and !$this->isSleeping()){
if($diff > 0.0625){
$revert = true;
$this->server->getLogger()->warning($this->getServer()->getLanguage()->translateString("pocketmine.player.invalidMove", [$this->getName()]));
}
if($this->isSurvival() and !$revert and $diff > 0.0625){
$ev = new PlayerIllegalMoveEvent($this, $newPos);
$ev->setCancelled($this->allowMovementCheats);
$this->server->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$revert = true;
$this->server->getLogger()->warning($this->getServer()->getLanguage()->translateString("pocketmine.player.invalidMove", [$this->getName()]));
}
}
@ -1407,7 +1459,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->checkNearEntities($tickDiff);
}
$this->speed = $from->subtract($to);
$this->speed = ($to->subtract($from))->divide($tickDiff);
}elseif($distanceSquared == 0){
$this->speed = new Vector3(0, 0, 0);
}
@ -1421,7 +1473,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->lastYaw = $from->yaw;
$this->lastPitch = $from->pitch;
$this->sendPosition($from, $from->yaw, $from->pitch, 1);
$this->sendPosition($from, $from->yaw, $from->pitch, MovePlayerPacket::MODE_RESET);
$this->forceMovement = new Vector3($from->x, $from->y, $from->z);
}else{
$this->forceMovement = null;
@ -1499,9 +1551,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->timings->startTiming();
if($this->spawned){
if(!$this->isSleeping()){
$this->processMovement($tickDiff);
}
$this->processMovement($tickDiff);
$this->entityBaseTick($tickDiff);
if(!$this->isSpectator() and $this->speed !== null){
@ -1534,6 +1584,15 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->timings->stopTiming();
//TODO: remove this workaround (broken client MCPE 1.0.0)
if(count($this->messageQueue) > 0){
$pk = new TextPacket();
$pk->type = TextPacket::TYPE_RAW;
$pk->message = implode("\n", $this->messageQueue);
$this->dataPacket($pk);
$this->messageQueue = [];
}
return true;
}
@ -1667,7 +1726,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->server->saveOfflinePlayerData($this->username, $nbt, true);
}
parent::__construct($this->level->getChunk($nbt["Pos"][0] >> 4, $nbt["Pos"][2] >> 4, true), $nbt);
parent::__construct($this->level, $nbt);
$this->loggedIn = true;
$this->server->addOnlinePlayer($this);
@ -1861,13 +1920,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break;
case ProtocolInfo::MOVE_PLAYER_PACKET:
if($this->teleportPosition !== null){
break;
}
$newPos = new Vector3($packet->x, $packet->y - $this->getEyeHeight(), $packet->z);
if($newPos->distanceSquared($this) < 0.01){ //player hasn't moved, just client spamming packets
if($newPos->distanceSquared($this) == 0 and ($packet->yaw % 360) === $this->yaw and ($packet->pitch % 360) === $this->pitch){ //player hasn't moved, just client spamming packets
break;
}
@ -1877,8 +1932,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->forceMovement = new Vector3($this->x, $this->y, $this->z);
}
if($this->forceMovement instanceof Vector3 and (($dist = $newPos->distanceSquared($this->forceMovement)) > 0.1 or $revert)){
$this->sendPosition($this->forceMovement, $packet->yaw, $packet->pitch);
if($this->teleportPosition !== null or ($this->forceMovement instanceof Vector3 and ($newPos->distanceSquared($this->forceMovement) > 0.1 or $revert))){
$this->sendPosition($this->forceMovement, $packet->yaw, $packet->pitch, MovePlayerPacket::MODE_RESET);
}else{
$packet->yaw %= 360;
$packet->pitch %= 360;
@ -1889,13 +1944,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->setRotation($packet->yaw, $packet->pitch);
$this->newPosition = $newPos;
$this->forceMovement = null;
}
$this->forceMovement = null;
break;
case ProtocolInfo::ADVENTURE_SETTINGS_PACKET:
//TODO: player abilities, check for other changes
if($packet->isFlying and !$this->allowFlight){
if($packet->isFlying and !$this->allowFlight and !$this->server->getAllowFlight()){
$this->kick("Flying is not enabled on this server");
break;
}else{
@ -1974,7 +2029,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
break;
case ProtocolInfo::USE_ITEM_PACKET:
if($this->spawned === false or !$this->isAlive() or $this->blocked){
if($this->spawned === false or !$this->isAlive()){
break;
}
@ -2060,7 +2115,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
]);
$f = 1.5;
$snowball = Entity::createEntity("Snowball", $this->chunk, $nbt, $this);
$snowball = Entity::createEntity("Snowball", $this->getLevel(), $nbt, $this);
$snowball->setMotion($snowball->getMotion()->multiply($f));
if($this->isSurvival()){
$item->setCount($item->getCount() - 1);
@ -2084,7 +2139,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
break;
case ProtocolInfo::PLAYER_ACTION_PACKET:
if($this->spawned === false or $this->blocked === true or (!$this->isAlive() and $packet->action !== PlayerActionPacket::ACTION_RESPAWN and $packet->action !== PlayerActionPacket::ACTION_DIMENSION_CHANGE)){
if($this->spawned === false or (!$this->isAlive() and $packet->action !== PlayerActionPacket::ACTION_RESPAWN and $packet->action !== PlayerActionPacket::ACTION_DIMENSION_CHANGE)){
break;
}
@ -2106,12 +2161,15 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$block = $target->getSide($packet->face);
if($block->getId() === Block::FIRE){
$this->level->setBlock($block, new Air());
break;
}
$this->lastBreak = microtime(true);
break;
case PlayerActionPacket::ACTION_ABORT_BREAK:
$this->lastBreak = PHP_INT_MAX;
break;
case PlayerActionPacket::ACTION_STOP_BREAK:
break;
case PlayerActionPacket::ACTION_RELEASE_ITEM:
if($this->startAction > -1 and $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION)){
if($this->inventory->getItemInHand()->getId() === Item::BOW){
@ -2142,7 +2200,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$diff = ($this->server->getTick() - $this->startAction);
$p = $diff / 20;
$f = min((($p ** 2) + $p * 2) / 3, 1) * 2;
$ev = new EntityShootBowEvent($this, $bow, Entity::createEntity("Arrow", $this->chunk, $nbt, $this, $f == 2 ? true : false), $f);
$ev = new EntityShootBowEvent($this, $bow, Entity::createEntity("Arrow", $this->getLevel(), $nbt, $this, $f == 2 ? true : false), $f);
if($f < 0.1 or $diff < 5){
$ev->setCancelled();
@ -2188,7 +2246,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk->eid = $this->getId();
$pk->event = EntityEventPacket::USE_ITEM;
$this->dataPacket($pk);
Server::broadcastPacket($this->getViewers(), $pk);
$this->server->broadcastPacket($this->getViewers(), $pk);
if($this->isSurvival()){
$slot = $this->inventory->getItemInHand();
@ -2238,11 +2296,11 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->inventory->sendContents($this);
$this->inventory->sendArmorContents($this);
$this->blocked = false;
$this->spawnToAll();
$this->scheduleUpdate();
break;
case PlayerActionPacket::ACTION_JUMP:
break 2;
case PlayerActionPacket::ACTION_START_SPRINT:
$ev = new PlayerToggleSprintEvent($this, true);
$this->server->getPluginManager()->callEvent($ev);
@ -2269,7 +2327,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}else{
$this->setSneaking(true);
}
break;
break 2;
case PlayerActionPacket::ACTION_STOP_SNEAK:
$ev = new PlayerToggleSneakEvent($this, false);
$this->server->getPluginManager()->callEvent($ev);
@ -2278,7 +2336,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}else{
$this->setSneaking(false);
}
break;
break 2;
default:
assert(false, "Unhandled player action " . $packet->action . " from " . $this->getName());
}
$this->startAction = -1;
@ -2286,7 +2346,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break;
case ProtocolInfo::REMOVE_BLOCK_PACKET:
if($this->spawned === false or $this->blocked === true or !$this->isAlive()){
if($this->spawned === false or !$this->isAlive()){
break;
}
$this->craftingType = 0;
@ -2301,7 +2361,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$oldItem = clone $item;
if($this->canInteract($vector->add(0.5, 0.5, 0.5), $this->isCreative() ? 13 : 6) and $this->level->useBreakOn($vector, $item, $this)){
if($this->canInteract($vector->add(0.5, 0.5, 0.5), $this->isCreative() ? 13 : 6) and $this->level->useBreakOn($vector, $item, $this, true)){
if($this->isSurvival()){
if(!$item->deepEquals($oldItem) or $item->getCount() !== $oldItem->getCount()){
$this->inventory->setItemInHand($item);
@ -2330,7 +2390,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break;
case ProtocolInfo::INTERACT_PACKET:
if($this->spawned === false or !$this->isAlive() or $this->blocked){
if($this->spawned === false or !$this->isAlive()){
break;
}
@ -2380,7 +2440,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
];
$damage = [
EntityDamageEvent::MODIFIER_BASE => isset($damageTable[$item->getId()]) ? $damageTable[$item->getId()] : 1,
EntityDamageEvent::MODIFIER_BASE => $damageTable[$item->getId()] ?? 1,
];
if(!$this->canInteract($target, 8)){
@ -2469,12 +2529,12 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk = new AnimatePacket();
$pk->eid = $this->getId();
$pk->action = $ev->getAnimationType();
Server::broadcastPacket($this->getViewers(), $pk);
$this->server->broadcastPacket($this->getViewers(), $pk);
break;
case ProtocolInfo::SET_HEALTH_PACKET: //Not used
break;
case ProtocolInfo::ENTITY_EVENT_PACKET:
if($this->spawned === false or $this->blocked === true or !$this->isAlive()){
if($this->spawned === false or !$this->isAlive()){
break;
}
$this->craftingType = 0;
@ -2501,9 +2561,15 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
break;
case ProtocolInfo::DROP_ITEM_PACKET:
if($this->spawned === false or $this->blocked === true or !$this->isAlive()){
if($this->spawned === false or !$this->isAlive()){
break;
}
if($packet->item->getId() === Item::AIR){
// Windows 10 Edition drops the contents of the crafting grid on container close - including air.
break;
}
$item = $this->inventory->getItemInHand();
$ev = new PlayerDropItemEvent($this, $item);
$this->server->getPluginManager()->callEvent($ev);
@ -2548,6 +2614,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$packet->message = TextFormat::clean($packet->message, $this->removeFormat);
foreach(explode("\n", $packet->message) as $message){
if(trim($message) != "" and strlen($message) <= 255 and $this->messageCounter-- > 0){
if(substr($message, 0, 2) === "./"){ //Command (./ = fast hack for old plugins post 0.16)
$message = substr($message, 1);
}
$ev = new PlayerCommandPreprocessEvent($this, $message);
if(mb_strlen($ev->getMessage(), "UTF-8") > 320){
@ -2558,9 +2628,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
if($ev->isCancelled()){
break;
}
if(substr($ev->getMessage(), 0, 2) === "./"){ //Command (./ = fast hack for old plugins post 0.16)
if(substr($ev->getMessage(), 0, 1) === "/"){
Timings::$playerCommandTimer->startTiming();
$this->server->dispatchCommand($ev->getPlayer(), substr($ev->getMessage(), 2));
$this->server->dispatchCommand($ev->getPlayer(), substr($ev->getMessage(), 1));
Timings::$playerCommandTimer->stopTiming();
}else{
$this->server->getPluginManager()->callEvent($ev = new PlayerChatEvent($this, $ev->getMessage()));
@ -2604,25 +2675,16 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break;
}
foreach($packet->input as $i => $item){
if($item->getDamage() === -1 or $item->getDamage() === 0xffff){
$item->setDamage(null);
}
if($i < 9 and $item->getId() > 0){
$item->setCount(1);
}
}
$canCraft = true;
if($recipe instanceof ShapedRecipe){
for($x = 0; $x < 3 and $canCraft; ++$x){
for($y = 0; $y < 3; ++$y){
/** @var Item $item */
$item = $packet->input[$y * 3 + $x];
$ingredient = $recipe->getIngredient($x, $y);
if($item->getCount() > 0){
if($ingredient === null or !$ingredient->deepEquals($item, $ingredient->getDamage() !== null, $ingredient->getCompoundTag() !== null)){
if($ingredient === null or !$ingredient->deepEquals($item, !$ingredient->hasAnyDamageValue(), $ingredient->hasCompoundTag())){
$canCraft = false;
break;
}
@ -2634,10 +2696,11 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
for($x = 0; $x < 3 and $canCraft; ++$x){
for($y = 0; $y < 3; ++$y){
/** @var Item $item */
$item = clone $packet->input[$y * 3 + $x];
foreach($needed as $k => $n){
if($n->deepEquals($item, $n->getDamage() !== null, $n->getCompoundTag() !== null)){
if($n->deepEquals($item, !$n->hasAnyDamageValue(), $n->hasCompoundTag())){
$remove = min($n->getCount(), $item->getCount());
$n->setCount($n->getCount() - $remove);
$item->setCount($item->getCount() - $remove);
@ -2676,8 +2739,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
foreach($ingredients as $ingredient){
$slot = -1;
foreach($this->inventory->getContents() as $index => $i){
if($ingredient->getId() !== 0 and $ingredient->deepEquals($i, $ingredient->getDamage() !== null) and ($i->getCount() - $used[$index]) >= 1){
foreach($this->inventory->getContents() as $index => $item){
if($ingredient->getId() !== 0 and $ingredient->equals($item, !$ingredient->hasAnyDamageValue(), $ingredient->hasCompoundTag()) and ($item->getCount() - $used[$index]) >= 1){
$slot = $index;
$used[$index]++;
break;
@ -2765,7 +2828,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break;
case ProtocolInfo::CONTAINER_SET_SLOT_PACKET:
if($this->spawned === false or $this->blocked === true or !$this->isAlive()){
if($this->spawned === false or !$this->isAlive()){
break;
}
@ -2843,7 +2906,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
break;
case ProtocolInfo::BLOCK_ENTITY_DATA_PACKET:
if($this->spawned === false or $this->blocked === true or !$this->isAlive()){
if($this->spawned === false or !$this->isAlive()){
break;
}
$this->craftingType = 0;
@ -2854,28 +2917,12 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
$t = $this->level->getTile($pos);
if($t instanceof Sign){
if($t instanceof Spawnable){
$nbt = new NBT(NBT::LITTLE_ENDIAN);
$nbt->read($packet->namedtag, false, true);
$nbt = $nbt->getData();
if($nbt["id"] !== Tile::SIGN){
if(!$t->updateCompoundTag($nbt, $this)){
$t->spawnTo($this);
}else{
$ev = new SignChangeEvent($t->getBlock(), $this, [
TextFormat::clean($nbt["Text1"], $this->removeFormat), TextFormat::clean($nbt["Text2"], $this->removeFormat), TextFormat::clean($nbt["Text3"], $this->removeFormat), TextFormat::clean($nbt["Text4"], $this->removeFormat)
]);
if(!isset($t->namedtag->Creator) or $t->namedtag["Creator"] !== $this->getRawUniqueId()){
$ev->setCancelled();
}
$this->server->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$t->setText($ev->getLine(0), $ev->getLine(1), $ev->getLine(2), $ev->getLine(3));
}else{
$t->spawnTo($this);
}
}
}
break;
@ -2888,16 +2935,33 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->dataPacket($pk);
break;
case ProtocolInfo::SET_PLAYER_GAME_TYPE_PACKET:
if($packet->gamemode !== $this->gamemode){
if(!$this->hasPermission("pocketmine.command.gamemode")){
$pk = new SetPlayerGameTypePacket();
$pk->gamemode = $this->gamemode & 0x01;
$this->dataPacket($pk);
$this->sendSettings();
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);
$this->sendSettings();
}
break;
case ProtocolInfo::ITEM_FRAME_DROP_ITEM_PACKET:
if($this->spawned === false or !$this->isAlive()){
break;
}
$tile = $this->level->getTile($this->temporalVector->setComponents($packet->x, $packet->y, $packet->z));
if($tile instanceof ItemFrame){
if($this->isSpectator()){
$tile->spawnTo($this);
break;
}
$this->setGamemode($packet->gamemode, true);
if(lcg_value() <= $tile->getItemDropChance()){
$this->level->dropItem($tile->getBlock(), $tile->getItem());
}
$tile->setItem(null);
$tile->setItemRotation(0);
}
break;
default:
break;
@ -2938,6 +3002,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
return false;
}
/** @var string[] */
private $messageQueue = [];
/**
* Sends a direct chat message to a player
*
@ -2952,15 +3019,14 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$message = $message->getText();
}
$mes = explode("\n", $this->server->getLanguage()->translateString($message));
foreach($mes as $m){
if($m !== ""){
$pk = new TextPacket();
$pk->type = TextPacket::TYPE_RAW;
$pk->message = $m;
$this->dataPacket($pk);
}
}
//TODO: Remove this workaround (broken client MCPE 1.0.0)
$this->messageQueue[] = $this->server->getLanguage()->translateString($message);
/*
$pk = new TextPacket();
$pk->type = TextPacket::TYPE_RAW;
$pk->message = $this->server->getLanguage()->translateString($message);
$this->dataPacket($pk);
*/
}
public function sendTranslation($message, array $parameters = []){
@ -3076,7 +3142,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->loadQueue = [];
$this->hasSpawned = [];
$this->spawnPosition = null;
unset($this->buffer);
}
if($this->perm !== null){
@ -3100,6 +3165,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
/**
* Handles player data saving
*
* @param bool $async
*/
public function save($async = false){
if($this->closed){
@ -3108,9 +3175,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
parent::saveNBT();
if($this->level instanceof Level){
$this->namedtag->Level = new StringTag("Level", $this->level->getName());
$this->namedtag->Level = new StringTag("Level", $this->level->getFolderName());
if($this->hasValidSpawnPosition()){
$this->namedtag["SpawnLevel"] = $this->spawnPosition->getLevel()->getName();
$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;
@ -3320,7 +3387,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
}
public function sendPosition(Vector3 $pos, $yaw = null, $pitch = null, $mode = 0, array $targets = null){
public function sendPosition(Vector3 $pos, $yaw = null, $pitch = null, $mode = MovePlayerPacket::MODE_NORMAL, array $targets = null){
$yaw = $yaw === null ? $this->yaw : $yaw;
$pitch = $pitch === null ? $this->pitch : $pitch;
@ -3335,11 +3402,13 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$pk->mode = $mode;
if($targets !== null){
Server::broadcastPacket($targets, $pk);
$this->server->broadcastPacket($targets, $pk);
}else{
$pk->eid = 0;
$this->dataPacket($pk);
}
$this->newPosition = null;
}
protected function checkChunks(){
@ -3390,7 +3459,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
}
$this->sendPosition($this, null, null, 1);
$this->sendPosition($this, null, null, MovePlayerPacket::MODE_RESET);
$this->spawnToAll();
$this->forceMovement = $this->teleportPosition;
$this->teleportPosition = null;
@ -3459,7 +3528,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
}
$this->forceMovement = new Vector3($this->x, $this->y, $this->z);
$this->sendPosition($this, $this->yaw, $this->pitch, 1);
$this->sendPosition($this, $this->yaw, $this->pitch, MovePlayerPacket::MODE_RESET);
$this->resetFallDistance();
$this->orderChunks();
@ -3535,20 +3604,24 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->server->getPlayerMetadata()->removeMetadata($this, $metadataKey, $plugin);
}
public function onChunkChanged(FullChunk $chunk){
$this->loadQueue[Level::chunkHash($chunk->getX(), $chunk->getZ())] = abs(($this->x >> 4) - $chunk->getX()) + abs(($this->z >> 4) - $chunk->getZ());
public function onChunkChanged(Chunk $chunk){
unset($this->usedChunks[Level::chunkHash($chunk->getX(), $chunk->getZ())]);
}
public function onChunkLoaded(FullChunk $chunk){
public function onChunkLoaded(Chunk $chunk){
}
public function onChunkPopulated(FullChunk $chunk){
public function onChunkPopulated(Chunk $chunk){
}
public function onChunkUnloaded(FullChunk $chunk){
public function onChunkUnloaded(Chunk $chunk){
}
public function onBlockChanged(Vector3 $block){
}
public function getLoaderId(){
@ -3558,29 +3631,4 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
public function isLoaderActive(){
return $this->isConnected();
}
/**
* @param int $chunkX
* @param int $chunkZ
* @param string $payload
* @param int $ordering
*
* @return DataPacket
*/
public static function getChunkCacheFromData($chunkX, $chunkZ, $payload, $ordering = FullChunkDataPacket::ORDER_COLUMNS){
$pk = new FullChunkDataPacket();
$pk->chunkX = $chunkX;
$pk->chunkZ = $chunkZ;
$pk->order = $ordering;
$pk->data = $payload;
$pk->encode();
$batch = new BatchPacket();
$batch->payload = zlib_encode(Binary::writeUnsignedVarInt(strlen($pk->getBuffer())) . $pk->getBuffer(), ZLIB_ENCODING_DEFLATE, Server::getInstance()->networkCompressionLevel);
$batch->encode();
$batch->isEncoded = true;
return $batch;
}
}

View File

@ -27,7 +27,7 @@ namespace {
case is_array($var):
echo str_repeat(" ", $cnt) . "array(" . count($var) . ") {" . PHP_EOL;
foreach($var as $key => $value){
echo str_repeat(" ", $cnt + 1) . "[" . (is_integer($key) ? $key : '"' . $key . '"') . "]=>" . PHP_EOL;
echo str_repeat(" ", $cnt + 1) . "[" . (is_int($key) ? $key : '"' . $key . '"') . "]=>" . PHP_EOL;
++$cnt;
safe_var_dump($value);
--$cnt;
@ -70,14 +70,12 @@ namespace pocketmine {
use pocketmine\utils\ServerKiller;
use pocketmine\utils\Terminal;
use pocketmine\utils\Utils;
use pocketmine\wizard\Installer;
use pocketmine\wizard\SetupWizard;
use raklib\RakLib;
const VERSION = "1.6.1dev";
const API_VERSION = "2.1.0";
const VERSION = "1.6.2dev";
const API_VERSION = "3.0.0-ALPHA4";
const CODENAME = "Unleashed";
const MINECRAFT_VERSION = "v0.16.0.5 alpha";
const MINECRAFT_VERSION_NETWORK = "0.16.0.5";
/*
* Startup code. Do not look at it, it may harm you.
@ -112,10 +110,9 @@ namespace pocketmine {
}
require_once(\pocketmine\PATH . "src/spl/ClassLoader.php");
require_once(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
require_once(\pocketmine\PATH . "src/pocketmine/CompatibleClassLoader.php");
}
$autoloader = new CompatibleClassLoader();
$autoloader = new \BaseClassLoader();
$autoloader->addPath(\pocketmine\PATH . "src");
$autoloader->addPath(\pocketmine\PATH . "src" . DIRECTORY_SEPARATOR . "spl");
$autoloader->register(true);
@ -444,11 +441,6 @@ namespace pocketmine {
++$errors;
}
if(!extension_loaded("sqlite3")){
$logger->critical("Unable to find the SQLite3 extension.");
++$errors;
}
if(!extension_loaded("zlib")){
$logger->critical("Unable to find the Zlib extension.");
++$errors;
@ -461,9 +453,18 @@ namespace pocketmine {
exit(1); //Exit with error
}
if(file_exists(\pocketmine\PATH . ".git/refs/heads/master")){ //Found Git information!
define('pocketmine\GIT_COMMIT', strtolower(trim(file_get_contents(\pocketmine\PATH . ".git/refs/heads/master"))));
}else{ //Unknown :(
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)){
define('pocketmine\GIT_COMMIT', strtolower($ref));
}elseif(substr($ref, 0, 5) === "ref: "){
$refFile = \pocketmine\PATH . ".git/" . substr($ref, 5);
if(is_file($refFile)){
define('pocketmine\GIT_COMMIT', strtolower(trim(file_get_contents($refFile))));
}
}
}
if(!defined('pocketmine\GIT_COMMIT')){ //Unknown :(
define('pocketmine\GIT_COMMIT', str_repeat("00", 20));
}
@ -471,32 +472,53 @@ namespace pocketmine {
@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"])){
new Installer();
$installer = new SetupWizard();
if(!$installer->run()){
$logger->shutdown();
$logger->join();
exit(-1);
}
}
if(\Phar::running(true) === ""){
$logger->warning("Non-packaged PocketMine-MP installation detected, do not use on production.");
}
ThreadManager::init();
$server = new Server($autoloader, $logger, \pocketmine\PATH, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
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");
$thread->quit();
try{
$thread->quit();
$logger->debug($thread->getThreadName() . " thread stopped successfully.");
}catch(\ThreadException $e){
++$erroredThreads;
$logger->debug("Could not stop " . $thread->getThreadName() . " thread: " . $e->getMessage());
}
}
$logger->shutdown();
$logger->join();
echo Terminal::$FORMAT_RESET . "\n";
echo Terminal::$FORMAT_RESET . PHP_EOL;
exit(0);
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);
}
}

View File

@ -31,18 +31,9 @@ use pocketmine\command\CommandSender;
use pocketmine\command\ConsoleCommandSender;
use pocketmine\command\PluginIdentifiableCommand;
use pocketmine\command\SimpleCommandMap;
use pocketmine\entity\Arrow;
use pocketmine\entity\Attribute;
use pocketmine\entity\Effect;
use pocketmine\entity\Entity;
use pocketmine\entity\FallingSand;
use pocketmine\entity\Human;
use pocketmine\entity\Item as DroppedItem;
use pocketmine\entity\PrimedTNT;
use pocketmine\entity\Snowball;
use pocketmine\entity\Squid;
use pocketmine\entity\Villager;
use pocketmine\entity\Zombie;
use pocketmine\event\HandlerList;
use pocketmine\event\level\LevelInitEvent;
use pocketmine\event\level\LevelLoadEvent;
@ -54,21 +45,21 @@ use pocketmine\event\TranslationContainer;
use pocketmine\inventory\CraftingManager;
use pocketmine\inventory\InventoryType;
use pocketmine\inventory\Recipe;
use pocketmine\inventory\ShapedRecipe;
use pocketmine\inventory\ShapelessRecipe;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\Item;
use pocketmine\lang\BaseLang;
use pocketmine\level\format\anvil\Anvil;
use pocketmine\level\format\leveldb\LevelDB;
use pocketmine\level\format\LevelProviderManager;
use pocketmine\level\format\mcregion\McRegion;
use pocketmine\level\format\io\LevelProviderManager;
use pocketmine\level\format\io\leveldb\LevelDB;
use pocketmine\level\format\io\region\Anvil;
use pocketmine\level\format\io\region\McRegion;
use pocketmine\level\format\io\region\PMAnvil;
use pocketmine\level\generator\biome\Biome;
use pocketmine\level\generator\Flat;
use pocketmine\level\generator\Generator;
use pocketmine\level\generator\hell\Nether;
use pocketmine\level\generator\normal\Normal;
use pocketmine\level\Level;
use pocketmine\level\LevelException;
use pocketmine\metadata\EntityMetadataStore;
use pocketmine\metadata\LevelMetadataStore;
use pocketmine\metadata\PlayerMetadataStore;
@ -85,8 +76,8 @@ use pocketmine\nbt\tag\StringTag;
use pocketmine\network\CompressBatchedTask;
use pocketmine\network\Network;
use pocketmine\network\protocol\BatchPacket;
use pocketmine\network\protocol\CraftingDataPacket;
use pocketmine\network\protocol\DataPacket;
use pocketmine\network\protocol\Info as ProtocolInfo;
use pocketmine\network\protocol\PlayerListPacket;
use pocketmine\network\query\QueryHandler;
use pocketmine\network\RakLibInterface;
@ -102,17 +93,10 @@ use pocketmine\plugin\ScriptPluginLoader;
use pocketmine\scheduler\FileWriteTask;
use pocketmine\scheduler\SendUsageTask;
use pocketmine\scheduler\ServerScheduler;
use pocketmine\tile\Chest;
use pocketmine\tile\EnchantTable;
use pocketmine\tile\FlowerPot;
use pocketmine\tile\Furnace;
use pocketmine\tile\Sign;
use pocketmine\tile\Skull;
use pocketmine\tile\Tile;
use pocketmine\updater\AutoUpdater;
use pocketmine\utils\Binary;
use pocketmine\utils\Config;
use pocketmine\utils\LevelException;
use pocketmine\utils\MainLogger;
use pocketmine\utils\Terminal;
use pocketmine\utils\TextFormat;
@ -170,8 +154,8 @@ class Server{
private $nextTick = 0;
private $tickAverage = [20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20];
private $useAverage = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
private $maxTick = 20;
private $maxUse = 0;
private $currentTPS = 20;
private $currentUse = 0;
private $sendUsageTicker = 0;
@ -185,7 +169,6 @@ class Server{
/** @var CommandReader */
private $console = null;
private $consoleThreaded;
/** @var SimpleCommandMap */
private $commandMap = null;
@ -302,7 +285,7 @@ class Server{
* @return string
*/
public function getVersion(){
return \pocketmine\MINECRAFT_VERSION;
return ProtocolInfo::MINECRAFT_VERSION;
}
/**
@ -620,7 +603,7 @@ class Server{
* @return float
*/
public function getTicksPerSecond(){
return round($this->maxTick, 2);
return round($this->currentTPS, 2);
}
/**
@ -638,7 +621,7 @@ class Server{
* @return float
*/
public function getTickUsage(){
return round($this->maxUse * 100, 2);
return round($this->currentUse * 100, 2);
}
/**
@ -1021,13 +1004,13 @@ class Server{
$generator = Generator::getGenerator($this->getLevelType());
}
if(($provider = LevelProviderManager::getProviderByName($providerName = $this->getProperty("level-settings.default-format", "mcregion"))) === null){
$provider = LevelProviderManager::getProviderByName($providerName = "mcregion");
if(($provider = LevelProviderManager::getProviderByName($providerName = $this->getProperty("level-settings.default-format", "pmanvil"))) === null){
$provider = LevelProviderManager::getProviderByName($providerName = "pmanvil");
}
try{
$path = $this->getDataPath() . "worlds/" . $name . "/";
/** @var \pocketmine\level\format\LevelProvider $provider */
/** @var \pocketmine\level\format\io\LevelProvider $provider */
$provider::generate($path, $name, $seed, $generator, $options);
$level = new Level($this, $name, $path, $provider);
@ -1466,7 +1449,11 @@ class Server{
define('pocketmine\DEBUG', (int) $this->getProperty("debug.level", 1));
ini_set('assert.exception', 1);
if(((int) ini_get('zend.assertions')) > 0 and ((bool) $this->getProperty("debug.assertions.warn-if-enabled", true)) !== false){
$this->logger->warning("Debugging assertions are enabled, this may impact on performance. To disable them, set `zend.assertions = -1` in php.ini.");
}
ini_set('assert.exception', (bool) $this->getProperty("debug.assertions.throw-exception", 0));
if($this->logger instanceof MainLogger){
$this->logger->setLogDebug(\pocketmine\DEBUG > 1);
@ -1500,9 +1487,8 @@ class Server{
$this->consoleSender = new ConsoleCommandSender();
$this->commandMap = new SimpleCommandMap($this);
$this->registerEntities();
$this->registerTiles();
Entity::init();
Tile::init();
InventoryType::init();
Block::init();
Enchantment::init();
@ -1530,11 +1516,12 @@ class Server{
$this->enablePlugins(PluginLoadOrder::STARTUP);
LevelProviderManager::addProvider($this, Anvil::class);
LevelProviderManager::addProvider($this, McRegion::class);
LevelProviderManager::addProvider(Anvil::class);
LevelProviderManager::addProvider(McRegion::class);
LevelProviderManager::addProvider(PMAnvil::class);
if(extension_loaded("leveldb")){
$this->logger->debug($this->getLanguage()->translateString("pocketmine.debug.enable"));
LevelProviderManager::addProvider($this, LevelDB::class);
LevelProviderManager::addProvider(LevelDB::class);
}
@ -1704,11 +1691,11 @@ class Server{
* @param Player[] $players
* @param DataPacket $packet
*/
public static function broadcastPacket(array $players, DataPacket $packet){
public function broadcastPacket(array $players, DataPacket $packet){
$packet->encode();
$packet->isEncoded = true;
if(Network::$BATCH_THRESHOLD >= 0 and strlen($packet->buffer) >= Network::$BATCH_THRESHOLD){
Server::getInstance()->batchPackets($players, [$packet->buffer], false);
$this->batchPackets($players, [$packet->buffer], false);
return;
}
@ -1818,8 +1805,6 @@ class Server{
* @param string $commandLine
*
* @return bool
*
* @throws \Exception
*/
public function dispatchCommand(CommandSender $sender, $commandLine){
if($this->commandMap->dispatch($sender, $commandLine)){
@ -2100,7 +2085,7 @@ class Server{
$next = $this->nextTick - 0.0001;
if($next > microtime(true)){
try{
time_sleep_until($next);
@time_sleep_until($next);
}catch(\Throwable $e){
//Sometimes $next is less than the current time. High load?
}
@ -2114,7 +2099,7 @@ class Server{
}
$this->sendFullPlayerListData($player);
$this->sendRecipeList($player);
$player->dataPacket($this->craftingManager->getCraftingDataPacket());
}
public function addPlayer($identifier, Player $player){
@ -2135,7 +2120,7 @@ class Server{
$pk = new PlayerListPacket();
$pk->type = PlayerListPacket::TYPE_REMOVE;
$pk->entries[] = [$player->getUniqueId()];
Server::broadcastPacket($this->playerList, $pk);
$this->broadcastPacket($this->playerList, $pk);
}
}
@ -2143,14 +2128,14 @@ class Server{
$pk = new PlayerListPacket();
$pk->type = PlayerListPacket::TYPE_ADD;
$pk->entries[] = [$uuid, $entityId, $name, $skinId, $skinData];
Server::broadcastPacket($players === null ? $this->playerList : $players, $pk);
$this->broadcastPacket($players === null ? $this->playerList : $players, $pk);
}
public function removePlayerListData(UUID $uuid, array $players = null){
$pk = new PlayerListPacket();
$pk->type = PlayerListPacket::TYPE_REMOVE;
$pk->entries[] = [$uuid];
Server::broadcastPacket($players === null ? $this->playerList : $players, $pk);
$this->broadcastPacket($players === null ? $this->playerList : $players, $pk);
}
public function sendFullPlayerListData(Player $p){
@ -2166,25 +2151,6 @@ class Server{
$p->dataPacket($pk);
}
public function sendRecipeList(Player $p){
$pk = new CraftingDataPacket();
$pk->cleanRecipes = true;
foreach($this->getCraftingManager()->getRecipes() as $recipe){
if($recipe instanceof ShapedRecipe){
$pk->addShapedRecipe($recipe);
}elseif($recipe instanceof ShapelessRecipe){
$pk->addShapelessRecipe($recipe);
}
}
foreach($this->getCraftingManager()->getFurnaceRecipes() as $recipe){
$pk->addFurnaceRecipe($recipe);
}
$p->dataPacket($pk);
}
private function checkTickUpdates($currentTick, $tickTime){
foreach($this->players as $p){
if(!$p->loggedIn and ($tickTime - $p->creationTime) >= 10){
@ -2298,8 +2264,8 @@ class Server{
" | Memory " . $usage .
" | U " . round($this->network->getUpload() / 1024, 2) .
" D " . round($this->network->getDownload() / 1024, 2) .
" kB/s | TPS " . $this->getTicksPerSecond() .
" | Load " . $this->getTickUsage() . "%\x07";
" kB/s | TPS " . $this->getTicksPerSecondAverage() .
" | Load " . $this->getTickUsageAverage() . "%\x07";
$this->network->resetStatistics();
}
@ -2363,8 +2329,8 @@ class Server{
if(($this->tickCounter & 0b1111) === 0){
$this->titleTick();
$this->maxTick = 20;
$this->maxUse = 0;
$this->currentTPS = 20;
$this->currentUse = 0;
if(($this->tickCounter & 0b111111111) === 0){
try{
@ -2409,23 +2375,15 @@ class Server{
Timings::$serverTickTimer->stopTiming();
$now = microtime(true);
$tick = min(20, 1 / max(0.001, $now - $tickTime));
$use = min(1, ($now - $tickTime) / 0.05);
$this->currentTPS = min(20, 1 / max(0.001, $now - $tickTime));
$this->currentUse = min(1, ($now - $tickTime) / 0.05);
TimingsHandler::tick($tick <= $this->profilingTickRate);
if($this->maxTick > $tick){
$this->maxTick = $tick;
}
if($this->maxUse < $use){
$this->maxUse = $use;
}
TimingsHandler::tick($this->currentTPS <= $this->profilingTickRate);
array_shift($this->tickAverage);
$this->tickAverage[] = $tick;
$this->tickAverage[] = $this->currentTPS;
array_shift($this->useAverage);
$this->useAverage[] = $use;
$this->useAverage[] = $this->currentUse;
if(($this->nextTick - $tickTime) < -1){
$this->nextTick = $tickTime;
@ -2435,27 +2393,4 @@ class Server{
return true;
}
private function registerEntities(){
Entity::registerEntity(Arrow::class);
Entity::registerEntity(DroppedItem::class);
Entity::registerEntity(FallingSand::class);
Entity::registerEntity(PrimedTNT::class);
Entity::registerEntity(Snowball::class);
Entity::registerEntity(Villager::class);
Entity::registerEntity(Zombie::class);
Entity::registerEntity(Squid::class);
Entity::registerEntity(Human::class, true);
}
private function registerTiles(){
Tile::registerTile(Chest::class);
Tile::registerTile(EnchantTable::class);
Tile::registerTile(FlowerPot::class);
Tile::registerTile(Furnace::class);
Tile::registerTile(Sign::class);
Tile::registerTile(Skull::class);
}
}

View File

@ -45,7 +45,6 @@ abstract class Thread extends \Thread{
if(!interface_exists("ClassLoader", false)){
require(\pocketmine\PATH . "src/spl/ClassLoader.php");
require(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
require(\pocketmine\PATH . "src/pocketmine/CompatibleClassLoader.php");
}
if($this->classLoader !== null){
$this->classLoader->register(true);

View File

@ -46,7 +46,6 @@ abstract class Worker extends \Worker{
if(!interface_exists("ClassLoader", false)){
require(\pocketmine\PATH . "src/spl/ClassLoader.php");
require(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
require(\pocketmine\PATH . "src/pocketmine/CompatibleClassLoader.php");
}
if($this->classLoader !== null){
$this->classLoader->register(true);

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class ActivatorRail extends Solid{
class ActivatorRail extends Rail{
protected $id = self::ACTIVATOR_RAIL;

View File

@ -21,6 +21,7 @@
namespace pocketmine\block;
use pocketmine\event\TranslationContainer;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
@ -65,7 +66,7 @@ class Bed extends Transparent{
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
if($player instanceof Player and !$isNight){
$player->sendMessage(TextFormat::GRAY . "You can only sleep at night");
$player->sendMessage(new TranslationContainer(TextFormat::GRAY . "%tile.bed.noSleep"));
return true;
}
@ -94,7 +95,7 @@ class Bed extends Transparent{
}
if($player instanceof Player and $player->sleepOn($b) === false){
$player->sendMessage(TextFormat::GRAY . "This bed is occupied");
$player->sendMessage(new TranslationContainer(TextFormat::GRAY . "%tile.bed.occupied"));
}
return true;

View File

@ -221,7 +221,8 @@ class Block extends Position implements BlockIds, Metadatable{
self::$list[self::WOOD2] = Wood2::class;
self::$list[self::ACACIA_WOOD_STAIRS] = AcaciaWoodStairs::class;
self::$list[self::DARK_OAK_WOOD_STAIRS] = DarkOakWoodStairs::class;
self::$list[self::PRISMARINE] = Prismarine::class;
self::$list[self::SEA_LANTERN] = SeaLantern::class;
self::$list[self::IRON_TRAPDOOR] = IronTrapdoor::class;
self::$list[self::HAY_BALE] = HayBale::class;
self::$list[self::CARPET] = Carpet::class;
@ -236,6 +237,8 @@ class Block extends Position implements BlockIds, Metadatable{
self::$list[self::FENCE_GATE_DARK_OAK] = FenceGateDarkOak::class;
self::$list[self::FENCE_GATE_ACACIA] = FenceGateAcacia::class;
self::$list[self::ITEM_FRAME_BLOCK] = ItemFrame::class;
self::$list[self::GRASS_PATH] = GrassPath::class;
self::$list[self::PODZOL] = Podzol::class;
@ -273,7 +276,7 @@ class Block extends Position implements BlockIds, Metadatable{
}else{
self::$lightFilter[$id] = 1;
for($data = 0; $data < 16; ++$data){
self::$fullList[($id << 4) | $data] = new Block($id, $data);
self::$fullList[($id << 4) | $data] = new UnknownBlock($id, $data);
}
}
}
@ -293,10 +296,10 @@ class Block extends Position implements BlockIds, Metadatable{
if($block !== null){
$block = new $block($meta);
}else{
$block = new Block($id, $meta);
$block = new UnknownBlock($id, $meta);
}
}catch(\RuntimeException $e){
$block = new Block($id, $meta);
$block = new UnknownBlock($id, $meta);
}
if($pos !== null){
@ -363,10 +366,10 @@ class Block extends Position implements BlockIds, Metadatable{
*
* @param int $type
*
* @return void
* @return int|bool
*/
public function onUpdate($type){
return false;
}
/**
@ -426,8 +429,6 @@ class Block extends Position implements BlockIds, Metadatable{
}
/**
* AKA: Block->canBeReplaced()
*
* @return bool
*/
public function canBeReplaced(){

View File

@ -161,6 +161,7 @@ interface BlockIds{
const BIRCH_WOOD_STAIRS = 135, BIRCH_WOODEN_STAIRS = 135;
const JUNGLE_WOOD_STAIRS = 136, JUNGLE_WOODEN_STAIRS = 136;
const BEACON = 138;
const COBBLESTONE_WALL = 139, COBBLE_WALL = 139, STONE_WALL = 139;
const FLOWER_POT_BLOCK = 140;
const CARROT_BLOCK = 141;
@ -190,7 +191,8 @@ interface BlockIds{
const SLIME_BLOCK = 165;
const IRON_TRAPDOOR = 167;
const PRISMARINE = 168;
const SEA_LANTERN = 169;
const HAY_BALE = 170;
const CARPET = 171;
const HARDENED_CLAY = 172;

View File

@ -29,7 +29,7 @@ use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\Player;
use pocketmine\tile\Furnace;
use pocketmine\tile\Furnace as TileFurnace;
use pocketmine\tile\Tile;
class BurningFurnace extends Solid{
@ -88,7 +88,7 @@ class BurningFurnace extends Solid{
}
}
Tile::createTile("Furnace", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
Tile::createTile("Furnace", $this->getLevel(), $nbt);
return true;
}
@ -101,11 +101,8 @@ class BurningFurnace extends Solid{
public function onActivate(Item $item, Player $player = null){
if($player instanceof Player){
$t = $this->getLevel()->getTile($this);
$furnace = false;
if($t instanceof Furnace){
$furnace = $t;
}else{
$furnace = $this->getLevel()->getTile($this);
if(!($furnace instanceof TileFurnace)){
$nbt = new CompoundTag("", [
new ListTag("Items", []),
new StringTag("id", Tile::FURNACE),
@ -114,7 +111,7 @@ class BurningFurnace extends Solid{
new IntTag("z", $this->z)
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$furnace = Tile::createTile("Furnace", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
$furnace = Tile::createTile("Furnace", $this->getLevel(), $nbt);
}
if(isset($furnace->namedtag->Lock) and $furnace->namedtag->Lock instanceof StringTag){

View File

@ -115,7 +115,7 @@ class Chest extends Transparent{
}
}
$tile = Tile::createTile("Chest", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
$tile = Tile::createTile("Chest", $this->getLevel(), $nbt);
if($chest instanceof TileChest and $tile instanceof TileChest){
$chest->pairWith($tile);
@ -155,7 +155,7 @@ class Chest extends Transparent{
new IntTag("z", $this->z)
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$chest = Tile::createTile("Chest", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
$chest = Tile::createTile("Chest", $this->getLevel(), $nbt);
}
if(isset($chest->namedtag->Lock) and $chest->namedtag->Lock instanceof StringTag){

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class DaylightSensor extends Solid{
class DaylightSensor extends Transparent{
protected $id = self::DAYLIGHT_SENSOR;
@ -32,4 +32,8 @@ class DaylightSensor extends Solid{
public function getName(){
return "Daylight Sensor";
}
public function getHardness(){
return 0.2;
}
}

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class DetectorRail extends Solid{
class DetectorRail extends Rail{
protected $id = self::DETECTOR_RAIL;

View File

@ -52,7 +52,7 @@ class DoublePlant extends Flowable{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent() === true){ //Replace with common break method
$this->getLevel()->setBlock($this, new Air(), false, false, true);
$this->getLevel()->setBlock($this, new Air(), true, true);
return Level::BLOCK_UPDATE_NORMAL;
}

View File

@ -51,7 +51,7 @@ class DoubleSlab extends Solid{
6 => "Quartz",
7 => "Nether Brick",
];
return "DoubleTag " . $names[$this->meta & 0x07] . " Slab";
return "Double " . $names[$this->meta & 0x07] . " Slab";
}
public function getDrops(Item $item){

View File

@ -51,7 +51,7 @@ class DoubleWoodSlab extends Solid{
6 => "",
7 => ""
];
return "DoubleTag " . $names[$this->meta & 0x07] . " Wooden Slab";
return "Double " . $names[$this->meta & 0x07] . " Wooden Slab";
}
public function getDrops(Item $item){

View File

@ -57,7 +57,7 @@ class EnchantingTable extends Transparent{
}
}
Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel(), $nbt);
return true;
}

View File

@ -37,7 +37,7 @@ class EndPortalFrame extends Solid{
}
public function getName(){
return "EndTag Portal Frame";
return "End Portal Frame";
}
public function getHardness(){

View File

@ -32,7 +32,7 @@ class EndStone extends Solid{
}
public function getName(){
return "EndTag Stone";
return "End Stone";
}
public function getToolType(){

View File

@ -22,7 +22,6 @@
namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\ByteTag;
@ -31,21 +30,14 @@ use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\Player;
abstract class Fallable extends Solid{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$ret = $this->getLevel()->setBlock($this, $this, true, true);
return $ret;
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::AIR or ($down instanceof Liquid)){
$fall = Entity::createEntity("FallingSand", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new CompoundTag("", [
$fall = Entity::createEntity("FallingSand", $this->getLevel(), new CompoundTag("", [
"Pos" => new ListTag("Pos", [
new DoubleTag("", $this->x + 0.5),
new DoubleTag("", $this->y),

View File

@ -52,14 +52,14 @@ class FlowerPot extends Flowable{
return true;
}
public function getBoundingBox(){
protected function recalculateBoundingBox(){
return new AxisAlignedBB(
$this->x + (5 / 16),
$this->x + 0.3125,
$this->y,
$this->z + (5 / 16),
$this->x + (11 / 16),
$this->y + (6 / 16),
$this->z + (11 / 16)
$this->z + 0.3125,
$this->x + 0.6875,
$this->y + 0.375,
$this->z + 0.6875
);
}
@ -85,7 +85,7 @@ class FlowerPot extends Flowable{
}
}
Tile::createTile(Tile::FLOWER_POT, $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
Tile::createTile(Tile::FLOWER_POT, $this->getLevel(), $nbt);
return true;
}
@ -107,7 +107,7 @@ class FlowerPot extends Flowable{
return false;
}
if(!$pot->canAddItem($item)){
return false;
return true;
}
$this->setDamage(self::STATE_FULL); //specific damage value is unnecessary, it just needs to be non-zero to show an item.

View File

@ -0,0 +1,148 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\nbt\tag\{
ByteTag, CompoundTag, FloatTag, IntTag, StringTag
};
use pocketmine\Player;
use pocketmine\tile\ItemFrame as TileItemFrame;
use pocketmine\tile\Tile;
class ItemFrame extends Flowable{
protected $id = Block::ITEM_FRAME_BLOCK;
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){
return "Item Frame";
}
public function canBeActivated(){
return true;
}
public function onActivate(Item $item, Player $player = null){
$tile = $this->level->getTile($this);
if(!($tile instanceof TileItemFrame)){
$nbt = new CompoundTag("", [
new StringTag("id", Tile::ITEM_FRAME),
new IntTag("x", $this->x),
new IntTag("y", $this->y),
new IntTag("z", $this->z),
new FloatTag("ItemDropChance", 1.0),
new ByteTag("ItemRotation", 0)
]);
$tile = Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), $nbt);
}
if($tile->hasItem()){
$tile->setItemRotation(($tile->getItemRotation() + 1) % 8);
}else{
if($item->getCount() > 0){
$frameItem = clone $item;
$frameItem->setCount(1);
$item->setCount($item->getCount() - 1);
$tile->setItem($frameItem);
if($player instanceof Player and $player->isSurvival()){
$player->getInventory()->setItemInHand($item->getCount() <= 0 ? Item::get(Item::AIR) : $item);
}
}
}
return true;
}
public function onBreak(Item $item){
$tile = $this->level->getTile($this);
if($tile instanceof TileItemFrame){
//TODO: add events
if(lcg_value() <= $tile->getItemDropChance() and $tile->getItem()->getId() !== Item::AIR){
$this->level->dropItem($tile->getBlock(), $tile->getItem());
}
}
return parent::onBreak($item);
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$sides = [
0 => 4,
1 => 5,
2 => 2,
3 => 3
];
if(!$this->getSide($sides[$this->meta])->isSolid()){
$this->level->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
}
return false;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
if($face === 0 or $face === 1){
return false;
}
$faces = [
2 => 3,
3 => 2,
4 => 1,
5 => 0
];
$this->meta = $faces[$face];
$this->level->setBlock($block, $this, true, true);
$nbt = new CompoundTag("", [
new StringTag("id", Tile::ITEM_FRAME),
new IntTag("x", $block->x),
new IntTag("y", $block->y),
new IntTag("z", $block->z),
new FloatTag("ItemDropChance", 1.0),
new ByteTag("ItemRotation", 0)
]);
if($item->hasCustomBlockData()){
foreach($item->getCustomBlockData() as $key => $v){
$nbt->{$key} = $v;
}
}
Tile::createTile(Tile::ITEM_FRAME, $this->getLevel(), $nbt);
return true;
}
public function getDrops(Item $item){
return [
[Item::ITEM_FRAME, 0, 1]
];
}
}

View File

@ -59,7 +59,7 @@ class Ladder extends Transparent{
protected function recalculateBoundingBox(){
$f = 0.125;
$f = 0.1875;
if($this->meta === 2){
return new AxisAlignedBB(
@ -124,11 +124,16 @@ class Ladder extends Transparent{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
/*if($this->getSide(0)->getId() === self::AIR){ //Replace with common break method
Server::getInstance()->api->entity->drop($this, Item::get(LADDER, 0, 1));
$this->getLevel()->setBlock($this, new Air(), true, true, true);
$sides = [
2 => 3,
3 => 2,
4 => 5,
5 => 4
];
if(!$this->getSide($sides[$this->meta])->isSolid()){ //Replace with common break method
$this->level->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}*/
}
}
return false;

View File

@ -129,7 +129,7 @@ class Leaves extends Transparent{
if($type === Level::BLOCK_UPDATE_NORMAL){
if(($this->meta & 0b00001100) === 0){
$this->meta |= 0x08;
$this->getLevel()->setBlock($this, $this, false, false, true);
$this->getLevel()->setBlock($this, $this, true, false);
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if(($this->meta & 0b00001100) === 0x08){

View File

@ -112,7 +112,7 @@ class Leaves2 extends Leaves{
if($type === Level::BLOCK_UPDATE_NORMAL){
if(($this->meta & 0b00001100) === 0){
$this->meta |= 0x08;
$this->getLevel()->setBlock($this, $this, false, false, true);
$this->getLevel()->setBlock($this, $this, true, false);
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if(($this->meta & 0b00001100) === 0x08){

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class Lever extends Solid{
class Lever extends Flowable{
protected $id = self::LEVER;

View File

@ -25,7 +25,7 @@ use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\Player;
class LitPumpkin extends Solid{
class LitPumpkin extends Pumpkin{
protected $id = self::LIT_PUMPKIN;
@ -33,28 +33,7 @@ class LitPumpkin extends Solid{
return 15;
}
public function getHardness(){
return 1;
}
public function getToolType(){
return Tool::TYPE_AXE;
}
public function getName(){
return "Jack o'Lantern";
}
public function __construct($meta = 0){
$this->meta = $meta;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
if($player instanceof Player){
$this->meta = ((int) $player->getDirection() + 5) % 4;
}
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
}

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class LitRedstoneLamp extends Solid{
class LitRedstoneLamp extends RedstoneLamp{
protected $id = self::LIT_REDSTONE_LAMP;

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class LitRedstoneTorch extends Solid{
class LitRedstoneTorch extends RedstoneTorch{
protected $id = self::REDSTONE_TORCH;

View File

@ -23,20 +23,20 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\Player;
use pocketmine\tile\Skull as SkullTile;
use pocketmine\tile\Spawnable;
use pocketmine\tile\Tile;
class MobHead extends Solid{
class MobHead extends Flowable{
protected $id = self::MOB_HEAD_BLOCK;
protected $type;
public function __construct($meta = 0){
$this->meta = $meta;
}
@ -49,6 +49,17 @@ class MobHead extends Solid{
return "Mob Head";
}
protected function recalculateBoundingBox(){
return new AxisAlignedBB(
$this->x + 0.25,
$this->y,
$this->z + 0.25,
$this->x + 0.75,
$this->y + 0.5,
$this->z + 0.75
);
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
if($face !== 0){
$this->meta = $face;
@ -70,14 +81,13 @@ class MobHead extends Solid{
$nbt->CustomName = new StringTag("CustomName", $item->getCustomName());
}
/** @var Spawnable $tile */
Tile::createTile("Skull", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
Tile::createTile("Skull", $this->getLevel(), $nbt);
return true;
}
return false;
}
public function onUpdate($type){
parent::onUpdate($type);
$faces = [
1 => 0,
2 => 3,
@ -93,15 +103,17 @@ class MobHead extends Solid{
}
}
return false;
return parent::onUpdate($type);
}
public function getDrops(Item $item){
if($this->meta === 3){
return [];
$tile = $this->level->getTile($this);
if($tile instanceof SkullTile){
return [
[Item::MOB_HEAD, $tile->getType(), 1]
];
}
return [
[Item::MOB_HEAD, $this->type, 1]
];
return [];
}
}

View File

@ -31,16 +31,6 @@ class NetherBrickFence extends Transparent{
$this->meta = $meta;
}
public function getBreakTime(Item $item){
if($item instanceof Air){
//Breaking by hand
return 10;
}else{
// Other breaktimes are equal to woodfences.
return parent::getBreakTime($item);
}
}
public function getHardness(){
return 2;
}

View File

@ -37,7 +37,7 @@ class Netherrack extends Solid{
}
public function getHardness(){
return 2;
return 0.4;
}
public function getToolType(){

View File

@ -41,7 +41,7 @@ class Obsidian extends Solid{
}
public function getHardness(){
return 50;
return 35;
}
public function getDrops(Item $item){

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class PoweredRail extends Solid{
class PoweredRail extends Rail{
protected $id = self::POWERED_RAIL;
public function __construct($meta = 0){

View File

@ -0,0 +1,65 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author Pocketmine Team
* @link http://www.pocketmine.net
*
*
*/
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
class Prismarine extends Solid{
const NORMAL = 0;
const DARK = 1;
const BRICKS = 2;
protected $id = self::PRISMARINE;
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getHardness(){
return 1.5;
}
public function getName(){
static $names = [
self::NORMAL => "Prismarine",
self::DARK => "Dark Prismarine",
self::BRICKS => "Prismarine Bricks",
];
return $names[$this->meta & 0x03] ?? "Unknown";
}
public function getToolType(){
return Tool::TYPE_PICKAXE;
}
public function getDrops(Item $item){
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return [
[$this->id, $this->meta & 0x03, 1],
];
}else{
return [];
}
}
}

View File

@ -29,8 +29,8 @@ class Pumpkin extends Solid{
protected $id = self::PUMPKIN;
public function __construct(){
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getHardness(){
@ -47,7 +47,7 @@ class Pumpkin extends Solid{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
if($player instanceof Player){
$this->meta = ((int) $player->getDirection() + 5) % 4;
$this->meta = ((int) $player->getDirection() + 1) % 4;
}
$this->getLevel()->setBlock($block, $this, true, true);

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class Rail extends Solid{
class Rail extends Flowable{
protected $id = self::RAIL;
@ -32,4 +32,8 @@ class Rail extends Solid{
public function getName(){
return "Rail";
}
public function getHardness(){
return 0.7;
}
}

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class RedstoneTorch extends Solid{
class RedstoneTorch extends Torch{
protected $id = self::REDSTONE_TORCH;

View File

@ -0,0 +1,52 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author Pocketmine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
use pocketmine\item\Item;
class SeaLantern extends Transparent{
protected $id = self::SEA_LANTERN;
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){
return "Sea Lantern";
}
public function getHardness(){
return 0.3;
}
public function getLightLevel(){
return 15;
}
public function getDrops(Item $item){
return [
[Item::PRISMARINE_CRYSTALS, 0, 3],
];
}
}

View File

@ -87,7 +87,7 @@ class SignPost extends Transparent{
$this->getLevel()->setBlock($block, new WallSign($this->meta), true);
}
Tile::createTile(Tile::SIGN, $this->getLevel()->getChunk($block->x >> 4, $block->z >> 4), $nbt);
Tile::createTile(Tile::SIGN, $this->getLevel(), $nbt);
return true;
}

View File

@ -21,10 +21,19 @@
namespace pocketmine\block;
use pocketmine\level\Level;
class StillLava extends Lava{
protected $id = self::STILL_LAVA;
public function onUpdate($type){
if($type !== Level::BLOCK_UPDATE_SCHEDULED){
return parent::onUpdate($type);
}
return false;
}
public function getName(){
return "Still Lava";
}

View File

@ -21,10 +21,19 @@
namespace pocketmine\block;
use pocketmine\level\Level;
class StillWater extends Water{
protected $id = self::STILL_WATER;
public function onUpdate($type){
if($type !== Level::BLOCK_UPDATE_SCHEDULED){
return parent::onUpdate($type);
}
return false;
}
public function getName(){
return "Still Water";
}

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class StoneButton extends Solid{
class StoneButton extends Flowable{
protected $id = self::STONE_BUTTON;
@ -32,4 +32,8 @@ class StoneButton extends Solid{
public function getName(){
return "Stone Button";
}
public function getHardness(){
return 0.5;
}
}

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class StonePressurePlate extends Solid{
class StonePressurePlate extends Transparent{
protected $id = self::STONE_PRESSURE_PLATE;
@ -32,4 +32,12 @@ class StonePressurePlate extends Solid{
public function getName(){
return "Stone Pressure Plate";
}
public function isSolid(){
return false;
}
public function getHardness(){
return 0.5;
}
}

View File

@ -57,7 +57,7 @@ class TNT extends Solid{
$this->getLevel()->setBlock($this, new Air(), true);
$mot = (new Random())->nextSignedFloat() * M_PI * 2;
$tnt = Entity::createEntity("PrimedTNT", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new CompoundTag("", [
$tnt = Entity::createEntity("PrimedTNT", $this->getLevel(), new CompoundTag("", [
"Pos" => new ListTag("Pos", [
new DoubleTag("", $this->x + 0.5),
new DoubleTag("", $this->y),

View File

@ -62,7 +62,7 @@ class TallGrass extends Flowable{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent() === true){ //Replace with common break method
$this->getLevel()->setBlock($this, new Air(), false, false, true);
$this->getLevel()->setBlock($this, new Air(), true, true);
return Level::BLOCK_UPDATE_NORMAL;
}

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class Tripwire extends Solid{
class Tripwire extends Flowable{
protected $id = self::TRIPWIRE;

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class TripwireHook extends Solid{
class TripwireHook extends Flowable{
protected $id = self::TRIPWIRE_HOOK;

View File

@ -19,10 +19,15 @@
*
*/
namespace pocketmine\utils;
namespace pocketmine\block;
class MonkeyPatch{
public function __construct(){
class UnknownBlock extends Transparent{
public function isSolid(){
return false;
}
public function getHardness(){
return 0;
}
}

View File

@ -146,7 +146,7 @@ class Vine extends Transparent{
if($type === Level::BLOCK_UPDATE_NORMAL){
/*if($this->getSide(0)->getId() === self::AIR){ //Replace with common break method
Server::getInstance()->api->entity->drop($this, Item::get(LADDER, 0, 1));
$this->getLevel()->setBlock($this, new Air(), true, true, true);
$this->getLevel()->setBlock($this, new Air(), true, true);
return Level::BLOCK_UPDATE_NORMAL;
}*/
}

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class WeightedPressurePlateHeavy extends Solid{
class WeightedPressurePlateHeavy extends WeightedPressurePlateLight{
protected $id = self::WEIGHTED_PRESSURE_PLATE_HEAVY;

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class WeightedPressurePlateLight extends Solid{
class WeightedPressurePlateLight extends Transparent{
protected $id = self::WEIGHTED_PRESSURE_PLATE_LIGHT;
@ -32,4 +32,12 @@ class WeightedPressurePlateLight extends Solid{
public function getName(){
return "Weighted Pressure Plate Light";
}
public function isSolid(){
return false;
}
public function getHardness(){
return 0.5;
}
}

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class WoodenButton extends Solid{
class WoodenButton extends StoneButton{
protected $id = self::WOODEN_BUTTON;

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
class WoodenPressurePlate extends Solid{
class WoodenPressurePlate extends StonePressurePlate{
protected $id = self::WOODEN_PRESSURE_PLATE;

View File

@ -65,9 +65,6 @@ abstract class Command{
/** @var string */
protected $usageMessage;
/** @var string */
private $permission = null;
/** @var string */
private $permissionMessage = null;
@ -108,13 +105,13 @@ abstract class Command{
*/
public function generateCustomCommandData(Player $player){
//TODO: fix command permission filtering on join
/*if(!$this->testPermission($player)){
/*if(!$this->testPermissionSilent($player)){
return null;
}*/
$customData = clone $this->commandData;
$customData->aliases = $this->getAliases();
/*foreach($customData->overloads as &$overload){
if(($p = @$overload->pocketminePermission) !== null and !$player->hasPermission($p)){
if(isset($overload->pocketminePermission) and !$player->hasPermission($overload->pocketminePermission)){
unset($overload);
}
}*/

View File

@ -30,7 +30,7 @@ interface CommandExecutor{
* @param string $label
* @param string[] $args
*
* @return boolean
* @return bool
*/
public function onCommand(CommandSender $sender, Command $command, $label, array $args);

View File

@ -41,7 +41,7 @@ interface CommandMap{
* @param CommandSender $sender
* @param string $cmdLine
*
* @return boolean
* @return bool
*/
public function dispatch(CommandSender $sender, $cmdLine);

View File

@ -19,20 +19,31 @@
*
*/
declare(strict_types = 1);
namespace pocketmine\command;
use pocketmine\Thread;
class CommandReader extends Thread{
private $readline;
const TYPE_READLINE = 0;
const TYPE_STREAM = 1;
const TYPE_PIPED = 2;
/** @var \Threaded */
protected $buffer;
private $shutdown = false;
private $type = self::TYPE_STREAM;
public function __construct(){
$this->buffer = new \Threaded;
$opts = getopt("", ["disable-readline"]);
$this->readline = (extension_loaded("readline") and !isset($opts["disable-readline"]));
if((extension_loaded("readline") and !isset($opts["disable-readline"]) and !$this->isPipe(STDIN))){
$this->type = self::TYPE_READLINE;
}
$this->start();
}
@ -40,23 +51,106 @@ class CommandReader extends Thread{
$this->shutdown = true;
}
private function readLine(){
if(!$this->readline){
public function quit(){
$wait = microtime(true) + 0.5;
while(microtime(true) < $wait){
if($this->isRunning()){
usleep(100000);
}else{
parent::quit();
return;
}
}
$message = "Thread blocked for unknown reason";
if($this->type === self::TYPE_PIPED){
$message = "STDIN is being piped from another location and the pipe is blocked, cannot stop safely";
}
throw new \ThreadException($message);
}
private function initStdin(){
global $stdin;
if(is_resource($stdin)){
fclose($stdin);
}
$stdin = fopen("php://stdin", "r");
if($this->isPipe($stdin)){
$this->type = self::TYPE_PIPED;
}else{
$this->type = self::TYPE_STREAM;
}
}
/**
* Checks if the specified stream is a FIFO pipe.
*
* @param resource $stream
* @return bool
*/
private function isPipe($stream) : bool{
return is_resource($stream) and ((function_exists("posix_isatty") and !posix_isatty($stream)) or ((fstat($stream)["mode"] & 0170000) === 0010000));
}
/**
* Reads a line from the console and adds it to the buffer. This method may block the thread.
*
* @return bool if the main execution should continue reading lines
*/
private function readLine() : bool{
$line = "";
if($this->type === self::TYPE_READLINE){
$line = trim(readline("> "));
if($line !== ""){
readline_add_history($line);
}else{
return true;
}
}else{
global $stdin;
if(!is_resource($stdin)){
return "";
$this->initStdin();
}
return trim(fgets($stdin));
}else{
$line = trim(readline("> "));
if($line != ""){
readline_add_history($line);
}
switch($this->type){
case self::TYPE_STREAM:
$r = [$stdin];
if(($count = stream_select($r, $w, $e, 0, 200000)) === 0){ //nothing changed in 200000 microseconds
return true;
}elseif($count === false){ //stream error
$this->initStdin();
}
return $line;
if(($raw = fgets($stdin)) !== false){
$line = trim($raw);
}else{
return false; //user pressed ctrl+c?
}
break;
case self::TYPE_PIPED:
if(($raw = fgets($stdin)) === false){ //broken pipe or EOF
$this->initStdin();
$this->synchronized(function(){
$this->wait(200000);
}); //prevent CPU waste if it's end of pipe
return true; //loop back round
}else{
$line = trim($raw);
}
break;
}
}
if($line !== ""){
$this->buffer[] = preg_replace("#\\x1b\\x5b([^\\x1b]*\\x7e|[\\x40-\\x50])#", "", $line);
}
return true;
}
/**
@ -73,24 +167,17 @@ class CommandReader extends Thread{
}
public function run(){
if(!$this->readline){
if($this->type !== self::TYPE_READLINE){
$this->initStdin();
}
while(!$this->shutdown and $this->readLine());
if($this->type !== self::TYPE_READLINE){
global $stdin;
$stdin = fopen("php://stdin", "r");
stream_set_blocking($stdin, 0);
fclose($stdin);
}
$lastLine = microtime(true);
while(!$this->shutdown){
if(($line = $this->readLine()) !== ""){
$this->buffer[] = preg_replace("#\\x1b\\x5b([^\\x1b]*\\x7e|[\\x40-\\x50])#", "", $line);
}elseif(!$this->shutdown and (microtime(true) - $lastLine) <= 0.1){ //Non blocking! Sleep to save CPU
$this->synchronized(function(){
$this->wait(10000);
});
}
$lastLine = microtime(true);
}
}
public function getThreadName(){

View File

@ -39,7 +39,7 @@ class BanListCommand extends VanillaCommand{
if(!$this->testPermission($sender)){
return true;
}
$list = $sender->getServer()->getNameBans();
if(isset($args[0])){
$args[0] = strtolower($args[0]);
if($args[0] === "ips"){

View File

@ -60,7 +60,7 @@ class DifficultyCommand extends VanillaCommand{
$pk = new SetDifficultyPacket();
$pk->difficulty = $sender->getServer()->getDifficulty();
Server::broadcastPacket($sender->getServer()->getOnlinePlayers(), $pk);
$sender->getServer()->broadcastPacket($sender->getServer()->getOnlinePlayers(), $pk);
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.difficulty.success", [$difficulty]));
}else{

View File

@ -90,6 +90,13 @@ class EffectCommand extends VanillaCommand{
if(count($args) >= 4){
$amplification = (int) $args[3];
if($amplification > 255){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.num.tooBig", [(string) $args[3], "255"]));
return true;
}elseif($amplification < 0){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.num.tooSmall", [(string) $args[3], "0"]));
return true;
}
}
if(count($args) >= 5){

View File

@ -77,10 +77,10 @@ class GamemodeCommand extends VanillaCommand{
$sender->sendMessage("Game mode change for " . $target->getName() . " failed!");
}else{
if($target === $sender){
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.gamemode.success.self", [Server::getGamemodeString($gameMode)]));
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.gamemode.success.self", ['blame', 'mojang', Server::getGamemodeString($gameMode)]));
}else{
$target->sendMessage(new TranslationContainer("gameMode.changed"));
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.gamemode.success.other", [$target->getName(), Server::getGamemodeString($gameMode)]));
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.gamemode.success.other", ['blame mojang', $target->getName(), Server::getGamemodeString($gameMode)]));
}
}

View File

@ -61,7 +61,7 @@ class HelpCommand extends VanillaCommand{
if($sender instanceof ConsoleCommandSender){
$pageHeight = PHP_INT_MAX;
}else{
$pageHeight = 5;
$pageHeight = 7;
}
if($command === ""){

View File

@ -123,8 +123,13 @@ class ParticleCommand extends VanillaCommand{
}
/**
* @param $name
* @param string $name
*
* @param Vector3 $pos
* @param int $xd
* @param float $yd
* @param float $zd
* @param int|null $data
* @return Particle
*/
private function getParticle($name, Vector3 $pos, $xd, $yd, $zd, $data){

View File

@ -82,6 +82,7 @@ class StatusCommand extends VanillaCommand{
}
$sender->sendMessage(TextFormat::GOLD . "Current TPS: {$tpsColor}{$server->getTicksPerSecond()} ({$server->getTickUsage()}%)");
$sender->sendMessage(TextFormat::GOLD . "Average TPS: {$tpsColor}{$server->getTicksPerSecondAverage()} ({$server->getTickUsageAverage()}%)");
$sender->sendMessage(TextFormat::GOLD . "Network upload: " . TextFormat::RED . round($server->getNetwork()->getUpload() / 1024, 2) . " kB/s");
$sender->sendMessage(TextFormat::GOLD . "Network download: " . TextFormat::RED . round($server->getNetwork()->getDownload() / 1024, 2) . " kB/s");

View File

@ -103,7 +103,7 @@ class TeleportCommand extends VanillaCommand{
}
$x = $this->getRelativeDouble($target->x, $sender, $args[$pos++]);
$y = $this->getRelativeDouble($target->y, $sender, $args[$pos++], 0, 128);
$y = $this->getRelativeDouble($target->y, $sender, $args[$pos++], 0, 256);
$z = $this->getRelativeDouble($target->z, $sender, $args[$pos++]);
$yaw = $target->getYaw();
$pitch = $target->getPitch();

View File

@ -21,7 +21,7 @@
namespace pocketmine\entity;
use pocketmine\level\format\FullChunk;
use pocketmine\level\Level;
use pocketmine\level\particle\CriticalParticle;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\protocol\AddEntityPacket;
@ -41,9 +41,9 @@ class Arrow extends Projectile{
protected $isCritical;
public function __construct(FullChunk $chunk, CompoundTag $nbt, Entity $shootingEntity = null, $critical = false){
public function __construct(Level $level, CompoundTag $nbt, Entity $shootingEntity = null, $critical = false){
$this->isCritical = (bool) $critical;
parent::__construct($chunk, $nbt, $shootingEntity);
parent::__construct($level, $nbt, $shootingEntity);
}
public function onUpdate($currentTick){

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
interface Attachable{
}

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Chicken extends Animal{
}

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
interface Colorable{
}

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Cow extends Animal{
}

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Creeper extends Monster implements Explosive{
}

View File

@ -22,6 +22,8 @@
namespace pocketmine\entity;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityEffectAddEvent;
use pocketmine\event\entity\EntityEffectRemoveEvent;
use pocketmine\event\entity\EntityRegainHealthEvent;
use pocketmine\event\player\PlayerExhaustEvent;
use pocketmine\network\protocol\MobEffectPacket;
@ -167,8 +169,8 @@ class Effect{
*
* @return $this
*/
public function setAmplifier($amplifier){
$this->amplifier = (int) $amplifier;
public function setAmplifier(int $amplifier){
$this->amplifier = $amplifier & 0xff;
return $this;
}
@ -251,6 +253,10 @@ class Effect{
}
public function add(Entity $entity, $modify = false, Effect $oldEffect = null){
$entity->getLevel()->getServer()->getPluginManager()->callEvent($ev = new EntityEffectAddEvent($entity, $this, $modify, $oldEffect));
if($ev->isCancelled()){
return;
}
if($entity instanceof Player){
$pk = new MobEffectPacket();
$pk->eid = 0;
@ -258,7 +264,7 @@ class Effect{
$pk->amplifier = $this->getAmplifier();
$pk->particles = $this->isVisible();
$pk->duration = $this->getDuration();
if($modify){
if($ev->willModify()){
$pk->eventId = MobEffectPacket::EVENT_MODIFY;
}else{
$pk->eventId = MobEffectPacket::EVENT_ADD;
@ -272,7 +278,7 @@ class Effect{
$entity->setNameTagVisible(false);
}elseif($this->id === Effect::SPEED){
$attr = $entity->getAttributeMap()->getAttribute(Attribute::MOVEMENT_SPEED);
if($modify and $oldEffect !== null){
if($ev->willModify() and $oldEffect !== null){
$speed = $attr->getValue() / (1 + 0.2 * $oldEffect->getAmplifier());
}else{
$speed = $attr->getValue();
@ -281,7 +287,7 @@ class Effect{
$attr->setValue($speed);
}elseif($this->id === Effect::SLOWNESS){
$attr = $entity->getAttributeMap()->getAttribute(Attribute::MOVEMENT_SPEED);
if($modify and $oldEffect !== null){
if($ev->willModify() and $oldEffect !== null){
$speed = $attr->getValue() / (1 - 0.15 * $oldEffect->getAmplifier());
}else{
$speed = $attr->getValue();
@ -292,6 +298,10 @@ class Effect{
}
public function remove(Entity $entity){
$entity->getLevel()->getServer()->getPluginManager()->callEvent($ev = new EntityEffectRemoveEvent($entity, $this));
if($ev->isCancelled()){
return;
}
if($entity instanceof Player){
$pk = new MobEffectPacket();
$pk->eid = 0;

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Egg extends Projectile{
}

View File

@ -1,28 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
use pocketmine\inventory\InventoryHolder;
class Enderman extends Monster implements InventoryHolder{
}

View File

@ -35,7 +35,6 @@ use pocketmine\event\entity\EntitySpawnEvent;
use pocketmine\event\entity\EntityTeleportEvent;
use pocketmine\event\Timings;
use pocketmine\level\format\Chunk;
use pocketmine\level\format\FullChunk;
use pocketmine\level\Level;
use pocketmine\level\Location;
use pocketmine\level\Position;
@ -101,13 +100,15 @@ abstract class Entity extends Location implements Metadatable{
* 49 (long)
* 50 (long)
* 51 (long)
* 52 (short) */
const DATA_BOUNDING_BOX_WIDTH = 53; //float
const DATA_BOUNDING_BOX_HEIGHT = 54; //float
/* 56 (vector3f)
* 57 (byte)
* 58 (float)
* 59 (float) */
* 52 (short)
* 53 (unknown) */
const DATA_BOUNDING_BOX_WIDTH = 54; //float
const DATA_BOUNDING_BOX_HEIGHT = 55; //float
const DATA_FUSE_LENGTH = 56; //int
/* 57 (vector3f)
* 58 (byte)
* 59 (float)
* 60 (float) */
const DATA_FLAG_ONFIRE = 0;
@ -137,18 +138,32 @@ abstract class Entity extends Location implements Metadatable{
const DATA_FLAG_TAMED = 24;
const DATA_FLAG_LEASHED = 25;
const DATA_FLAG_SHEARED = 26; //for sheep
const DATA_FLAG_FALL_FLYING = 27; //???
const DATA_FLAG_GLIDING = 27, DATA_FLAG_FALL_FLYING = 27;
const DATA_FLAG_ELDER = 28; //elder guardian
const DATA_FLAG_MOVING = 29;
const DATA_FLAG_BREATHING = 30; //hides bubbles if true
const DATA_FLAG_CHESTED = 31; //for mules?
const DATA_FLAG_STACKABLE = 32; //???
const DATA_FLAG_STACKABLE = 32;
const DATA_FLAG_IDLING = 36;
public static $entityCount = 1;
/** @var Entity[] */
private static $knownEntities = [];
private static $shortNames = [];
public static function init(){
Entity::registerEntity(Arrow::class);
Entity::registerEntity(FallingSand::class);
Entity::registerEntity(Item::class);
Entity::registerEntity(PrimedTNT::class);
Entity::registerEntity(Snowball::class);
Entity::registerEntity(Squid::class);
Entity::registerEntity(Villager::class);
Entity::registerEntity(Zombie::class);
Entity::registerEntity(Human::class, true);
}
/**
* @var Player[]
*/
@ -236,7 +251,6 @@ abstract class Entity extends Location implements Metadatable{
public $noDamageTicks;
protected $justCreated;
protected $fireProof;
private $invulnerable;
/** @var AttributeMap */
@ -255,10 +269,7 @@ abstract class Entity extends Location implements Metadatable{
protected $isPlayer = false;
public function __construct(FullChunk $chunk, CompoundTag $nbt){
assert($chunk !== null and $chunk->getProvider() !== null);
public function __construct(Level $level, CompoundTag $nbt){
$this->timings = Timings::getEntityTimings($this);
$this->isPlayer = $this instanceof Player;
@ -273,9 +284,10 @@ abstract class Entity extends Location implements Metadatable{
$this->justCreated = true;
$this->namedtag = $nbt;
$this->chunk = $chunk;
$this->setLevel($chunk->getProvider()->getLevel());
$this->server = $chunk->getProvider()->getLevel()->getServer();
$this->chunk = $level->getChunk($this->namedtag["Pos"][0] >> 4, $this->namedtag["Pos"][2] >> 4);
assert($this->chunk !== null);
$this->setLevel($level);
$this->server = $level->getServer();
$this->boundingBox = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
$this->setPositionAndRotation(
@ -287,6 +299,8 @@ abstract class Entity extends Location implements Metadatable{
$this->namedtag->Rotation[0],
$this->namedtag->Rotation[1]
);
$this->setMotion($this->temporalVector->setComponents($this->namedtag["Motion"][0], $this->namedtag["Motion"][1], $this->namedtag["Motion"][2]));
assert(!is_nan($this->x) and !is_infinite($this->x) and !is_nan($this->y) and !is_infinite($this->y) and !is_nan($this->z) and !is_infinite($this->z));
@ -371,6 +385,20 @@ abstract class Entity extends Location implements Metadatable{
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ALWAYS_SHOW_NAMETAG, $value);
}
/**
* @return float
*/
public function getScale(): float{
return $this->getDataProperty(self::DATA_SCALE);
}
/**
* @param float $value
*/
public function setScale(float $value){
$this->setDataProperty(self::DATA_SCALE, self::DATA_TYPE_FLOAT, $value);
}
public function isSneaking(){
return $this->getDataFlag(self::DATA_FLAGS, self::DATA_FLAG_SNEAKING);
}
@ -487,16 +515,16 @@ abstract class Entity extends Location implements Metadatable{
/**
* @param int|string $type
* @param FullChunk $chunk
* @param Level $level
* @param CompoundTag $nbt
* @param $args
*
* @return Entity
*/
public static function createEntity($type, FullChunk $chunk, CompoundTag $nbt, ...$args){
public static function createEntity($type, Level $level, CompoundTag $nbt, ...$args){
if(isset(self::$knownEntities[$type])){
$class = self::$knownEntities[$type];
return new $class($chunk, $nbt, ...$args);
return new $class($level, $nbt, ...$args);
}
return null;
@ -597,12 +625,14 @@ abstract class Entity extends Location implements Metadatable{
if(isset($this->namedtag->ActiveEffects)){
foreach($this->namedtag->ActiveEffects->getValue() as $e){
$amplifier = $e["Amplifier"] & 0xff; //0-255 only
$effect = Effect::getEffect($e["Id"]);
if($effect === null){
continue;
}
$effect->setAmplifier($e["Amplifier"])->setDuration($e["Duration"])->setVisible($e["ShowParticles"] > 0);
$effect->setAmplifier($amplifier)->setDuration($e["Duration"])->setVisible($e["ShowParticles"] > 0);
$this->addEffect($effect);
}
@ -920,10 +950,11 @@ abstract class Entity extends Location implements Metadatable{
}
if($this->fireTicks > 0){
if($this->fireProof){
$this->fireTicks -= 4 * $tickDiff;
if($this->fireTicks < 0){
$this->fireTicks = 0;
if($this->isFireProof()){
if($this->fireTicks > 1){
$this->fireTicks = 1;
}else{
$this->fireTicks -= 1;
}
}else{
if(!$this->hasEffect(Effect::FIRE_RESISTANCE) and (($this->fireTicks % 20) === 0 or $tickDiff > 20)){
@ -1049,6 +1080,10 @@ abstract class Entity extends Location implements Metadatable{
}
}
public function isFireProof() : bool{
return false;
}
public function getDirection(){
$rotation = ($this->yaw - 90) % 360;
if($rotation < 0){
@ -1276,6 +1311,8 @@ abstract class Entity extends Location implements Metadatable{
//TODO: big messy loop
}*/
assert(abs($dx) <= 20 and abs($dy) <= 20 and abs($dz) <= 20, "Movement distance is excessive: dx=$dx, dy=$dy, dz=$dz");
$list = $this->level->getCollisionCubes($this, $this->level->getTickRate() > 1 ? $this->boundingBox->getOffsetBoundingBox($dx, $dy, $dz) : $this->boundingBox->addCoord($dx, $dy, $dz), false);
foreach($list as $bb){
@ -1599,8 +1636,8 @@ abstract class Entity extends Location implements Metadatable{
if($this->chunk !== null){
$this->chunk->removeEntity($this);
}
if($this->level !== null){
$this->level->removeEntity($this);
if($this->getLevel() !== null){
$this->getLevel()->removeEntity($this);
}
}
}
@ -1609,6 +1646,7 @@ abstract class Entity extends Location implements Metadatable{
* @param int $id
* @param int $type
* @param mixed $value
* @param bool $send
*
* @return bool
*/

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
abstract class Hanging extends Entity implements Attachable{
}

View File

@ -236,7 +236,8 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
}
public function recalculateXpProgress() : float{
$this->setXpProgress($this->getRemainderXp() / self::getTotalXpForLevel($this->getXpLevel()));
$this->setXpProgress($progress = $this->getRemainderXp() / self::getTotalXpForLevel($this->getXpLevel()));
return $progress;
}
public static function getTotalXpForLevel(int $level) : int{
@ -346,36 +347,38 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
public function entityBaseTick($tickDiff = 1){
$hasUpdate = parent::entityBaseTick($tickDiff);
$food = $this->getFood();
$health = $this->getHealth();
if($food >= 18){
$this->foodTickTimer++;
if($this->foodTickTimer >= 80 and $health < $this->getMaxHealth()){
$this->heal(1, new EntityRegainHealthEvent($this, 1, EntityRegainHealthEvent::CAUSE_SATURATION));
$this->exhaust(3.0, PlayerExhaustEvent::CAUSE_HEALTH_REGEN);
$this->foodTickTimer = 0;
if($this->isAlive()){
$food = $this->getFood();
$health = $this->getHealth();
if($food >= 18){
$this->foodTickTimer++;
if($this->foodTickTimer >= 80 and $health < $this->getMaxHealth()){
$this->heal(1, new EntityRegainHealthEvent($this, 1, EntityRegainHealthEvent::CAUSE_SATURATION));
$this->exhaust(3.0, PlayerExhaustEvent::CAUSE_HEALTH_REGEN);
$this->foodTickTimer = 0;
}
}elseif($food === 0){
$this->foodTickTimer++;
if($this->foodTickTimer >= 80){
$diff = $this->server->getDifficulty();
$can = false;
if($diff === 1){
$can = $health > 10;
}elseif($diff === 2){
$can = $health > 1;
}elseif($diff === 3){
$can = true;
}
if($can){
$this->attack(1, new EntityDamageEvent($this, EntityDamageEvent::CAUSE_STARVATION, 1));
}elseif($food === 0){
$this->foodTickTimer++;
if($this->foodTickTimer >= 80){
$diff = $this->server->getDifficulty();
$can = false;
if($diff === 1){
$can = $health > 10;
}elseif($diff === 2){
$can = $health > 1;
}elseif($diff === 3){
$can = true;
}
if($can){
$this->attack(1, new EntityDamageEvent($this, EntityDamageEvent::CAUSE_STARVATION, 1));
}
}
}
}
if($food <= 6){
if($this->isSprinting()){
$this->setSprinting(false);
if($food <= 6){
if($this->isSprinting()){
$this->setSprinting(false);
}
}
}

View File

@ -25,7 +25,6 @@ use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\ItemDespawnEvent;
use pocketmine\event\entity\ItemSpawnEvent;
use pocketmine\item\Item as ItemItem;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ShortTag;
use pocketmine\nbt\tag\StringTag;
@ -160,7 +159,7 @@ class Item extends Entity{
public function saveNBT(){
parent::saveNBT();
$this->namedtag->Item = $this->item->nbtSerialize();
$this->namedtag->Item = $this->item->nbtSerialize(-1, "Item");
$this->namedtag->Health = new ShortTag("Health", $this->getHealth());
$this->namedtag->Age = new ShortTag("Age", $this->age);
$this->namedtag->PickupDelay = new ShortTag("PickupDelay", $this->pickupDelay);

View File

@ -32,7 +32,6 @@ use pocketmine\item\Item as ItemItem;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\ShortTag;
use pocketmine\network\protocol\EntityEventPacket;
use pocketmine\Server;
use pocketmine\utils\BlockIterator;
abstract class Living extends Entity implements Damageable{
@ -74,7 +73,7 @@ abstract class Living extends Entity implements Damageable{
$pk = new EntityEventPacket();
$pk->eid = $this->getId();
$pk->event = EntityEventPacket::RESPAWN;
Server::broadcastPacket($this->hasSpawned, $pk);
$this->server->broadcastPacket($this->hasSpawned, $pk);
}
}
@ -136,7 +135,7 @@ abstract class Living extends Entity implements Damageable{
$pk = new EntityEventPacket();
$pk->eid = $this->getId();
$pk->event = $this->getHealth() <= 0 ? EntityEventPacket::DEATH_ANIMATION : EntityEventPacket::HURT_ANIMATION; //Ouch!
Server::broadcastPacket($this->hasSpawned, $pk);
$this->server->broadcastPacket($this->hasSpawned, $pk);
$this->attackTime = 10; //0.5 seconds cooldown
}

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Minecart extends Vehicle{
}

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Ozelot extends Animal implements Tameable{
}

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Painting extends Hanging{
}

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Pig extends Animal implements Rideable{
}

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class PigZombie extends Zombie{
}

View File

@ -57,6 +57,9 @@ class PrimedTNT extends Entity implements Explosive{
}else{
$this->fuse = 80;
}
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_IGNITED, true);
$this->setDataProperty(self::DATA_FUSE_LENGTH, self::DATA_TYPE_INT, $this->fuse);
}
@ -81,6 +84,11 @@ class PrimedTNT extends Entity implements Explosive{
if($tickDiff <= 0 and !$this->justCreated){
return true;
}
if($this->fuse % 5 === 0){ //don't spam it every tick, it's not necessary
$this->setDataProperty(self::DATA_FUSE_LENGTH, self::DATA_TYPE_INT, $this->fuse);
}
$this->lastUpdate = $currentTick;
$hasUpdate = $this->entityBaseTick($tickDiff);

View File

@ -26,7 +26,7 @@ use pocketmine\event\entity\EntityDamageByChildEntityEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\ProjectileHitEvent;
use pocketmine\level\format\FullChunk;
use pocketmine\level\Level;
use pocketmine\level\MovingObjectPosition;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
@ -42,12 +42,12 @@ abstract class Projectile extends Entity{
public $hadCollision = false;
public function __construct(FullChunk $chunk, CompoundTag $nbt, Entity $shootingEntity = null){
public function __construct(Level $level, CompoundTag $nbt, Entity $shootingEntity = null){
$this->shootingEntity = $shootingEntity;
if($shootingEntity !== null){
$this->setDataProperty(self::DATA_SHOOTER_ID, self::DATA_TYPE_LONG, $shootingEntity->getId());
}
parent::__construct($chunk, $nbt);
parent::__construct($level, $nbt);
}
public function attack($damage, EntityDamageEvent $source){

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Sheep extends Animal implements Colorable{
}

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Silverfish extends Monster{
}

View File

@ -1,26 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Skeleton extends Monster implements ProjectileSource{
}

View File

@ -1,28 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Slime extends Living{
const DATA_SIZE = 16;
}

View File

@ -21,7 +21,7 @@
namespace pocketmine\entity;
use pocketmine\level\format\FullChunk;
use pocketmine\level\Level;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\protocol\AddEntityPacket;
use pocketmine\Player;
@ -36,8 +36,8 @@ class Snowball extends Projectile{
protected $gravity = 0.03;
protected $drag = 0.01;
public function __construct(FullChunk $chunk, CompoundTag $nbt, Entity $shootingEntity = null){
parent::__construct($chunk, $nbt, $shootingEntity);
public function __construct(Level $level, CompoundTag $nbt, Entity $shootingEntity = null){
parent::__construct($level, $nbt, $shootingEntity);
}
public function onUpdate($currentTick){

View File

@ -1,27 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\entity;
class Spider extends Monster{
}

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