Compare commits

...

345 Commits

Author SHA1 Message Date
e2986992c7 Fixed AxisAlignedBB infinite expansion 2014-08-28 21:11:49 +02:00
9fb46d8fe8 Fixed entity physics 2014-08-28 18:26:37 +02:00
eab86f5f90 Replaced array() with [] 2014-08-28 17:04:22 +02:00
2f2afe2336 Fixed #1966 Face Lit Pumkins correctly 2014-08-28 11:00:41 +02:00
f7de1ede3f Made PocketMine loader backwards-compatible 2014-08-27 21:30:36 +02:00
812ae09a06 Merge branch 'php-5.6' 2014-08-27 21:24:52 +02:00
e473cd5e67 Improved unloaded tile entity handling 2014-08-27 18:18:33 +02:00
9e5e4fb362 Fixed possible Level::getBlock() crash 2014-08-27 18:11:23 +02:00
afa98866e0 Fixed Item after-clone behaviour 2014-08-27 18:11:02 +02:00
90fa40de34 Added entity id names 2014-08-27 17:42:38 +02:00
e6234c4c4d Removed cli_set_process_title() check 2014-08-27 12:45:14 +02:00
8f66d03d99 Improved Item::get() 2014-08-27 12:43:54 +02:00
8e9da9c84e Improved safe_var_dump(), Inventory::addItem() Inventory::removeItem() using argument unpacking 2014-08-27 12:29:04 +02:00
759d7e2545 Initial PHP 5.6 features support 2014-08-27 12:21:01 +02:00
f4b92bcdfc Fixed #1980 2014-08-27 11:41:00 +02:00
f7e2d31f0a Check player online status, closes #1983 2014-08-27 11:28:49 +02:00
e0fc3784ad Throw exception when saving an already-closed player, closes #1981 2014-08-26 22:02:43 +02:00
bf5630dc0d Fixed #1926 Teleport to non-generated chunks 2014-08-26 16:45:51 +02:00
472431752b Dropped items and arrows get deleted on Y < 0 2014-08-26 16:19:45 +02:00
c40f9f65a5 Optimize imports 2014-08-26 11:54:24 +02:00
f74af12914 Improved chunk ticking, enabled again. Disable it setting chunk-ticking.per-tick to 0 2014-08-26 11:52:45 +02:00
d169734781 Improved chunk sending 2014-08-26 11:50:51 +02:00
35b86af2af Fixed furnace achievement check 2014-08-26 10:56:33 +02:00
706bc8e8db Fixed undefined index on furnace recipes 2014-08-26 00:05:40 +02:00
b542c5b9bd Added Furnace progress fire 2014-08-26 00:05:18 +02:00
69800c6d79 Fixed #1911 Implemented FurnaceInventory callback 2014-08-26 00:03:16 +02:00
ea9fc3c72e Fixed #1879 Tile entities were not saved on chunk unload 2014-08-26 00:02:20 +02:00
8b90281355 Fixed #1953 Increased item PickupDelay to 2.5 seconds 2014-08-25 23:38:35 +02:00
92cabced97 Ctrl+C handling and kill signals are working again 2014-08-25 23:24:18 +02:00
cb645fa288 Moved spl to PocketMine-SPL 2014-08-25 21:02:33 +02:00
bda597a71e Moved spl to PocketMine-SPL 2014-08-25 20:54:53 +02:00
d6a0e284e3 Workaround BaseChunk::setBlock() recursion issues 2014-08-25 17:08:02 +02:00
1795c8c5e3 Fixed Chests/Furnaces not dropping contents when broken 2014-08-25 16:59:04 +02:00
c3b1b59118 Fixed #1970 Breaking blocks does not remove tile entities 2014-08-25 16:55:52 +02:00
a0df0a8fff Fixed player fall damage 2014-08-25 16:53:20 +02:00
049103ab7a Improved Block selection and construction performance 2014-08-25 16:39:47 +02:00
84c63c48ca Improved NBT IntArray read/write 2014-08-25 16:28:46 +02:00
20e11bd408 Improved player onGround collision check 2014-08-25 15:48:12 +02:00
456760b334 Removed unloaded chunk check 2014-08-25 15:43:48 +02:00
46e502430e Added teleport flag to MovePlayerPacket, improves player movement 2014-08-25 13:01:39 +02:00
87b800ebb9 Fixed #1967 Glowstone dust -> Glowstone recipe 2014-08-25 11:33:47 +02:00
9fdafb87b4 Fixed #1962 Fake client-side player entities 2014-08-24 23:12:12 +02:00
1fcfef20b0 Implemented beds 2014-08-24 20:34:24 +02:00
6109505786 Implemented correct time offsets and speed 2014-08-24 20:34:06 +02:00
764937dda4 Fixed #1961 2014-08-24 18:08:14 +02:00
8bf36315ae Updated RakLib 2014-08-24 17:21:05 +02:00
1ea0531ec7 Added RakLib port checking option 2014-08-24 17:16:37 +02:00
c47e359262 Updated blocks bounding boxes 2014-08-24 16:30:56 +02:00
f0f9bccb4b Fixed #1960 2014-08-24 15:57:13 +02:00
214dcef1ea Improved Air block collision check 2014-08-24 15:55:34 +02:00
4edadd764c Improved Level::getBlock() 2014-08-24 14:30:43 +02:00
01ebe74974 Performance improvements in blocks and Entities 2014-08-24 14:08:17 +02:00
84ce5f1c73 Performance improvements in NBT reading/writing 2014-08-24 13:59:37 +02:00
93a2bd36e0 Require PHP >= 5.5 2014-08-24 13:33:03 +02:00
fdd59e4506 Fixed default memory-limit values 2014-08-23 20:14:41 +02:00
9b86b1d45b Added --enable-profiler parameter to use with @krakjoe profiler 2014-08-23 20:14:04 +02:00
1a38003bc4 Fixed /version 2014-08-22 19:39:24 +02:00
60ea4d0e96 Removed hardcoded Server name from source 2014-08-22 18:31:17 +02:00
6077190a62 Deprecated Server::loadPlugin(Plugin) in favor of Server::enablePlugin(Plugin) 2014-08-22 17:43:29 +02:00
57299b9a29 Fixed #1948 /whitelist list is now working 2014-08-22 13:23:56 +02:00
bb08da701b Fixed header logo in PR #1944 2014-08-22 11:30:15 +02:00
ee593fe5e4 Merge pull request #1944 from PEMapModder/patch-2
Cleaned Mycelium.php and fixed its potential crash
2014-08-22 11:22:10 +02:00
e8b1b0fab6 Cleaned Mycelium.php and fixed its potential crash
Crash report: http://crash.pocketmine.net/view/27500
2014-08-22 11:05:47 +08:00
4858c7d82e Merge pull request #1912 from Intyre/feature/block
EndPortal, EndStone, MonsterSpawner, Mycelium and Podzol blocks added
2014-08-21 19:34:51 +02:00
ecc9e1d223 EndPortal meta and Endstone breaktime 2014-08-21 19:26:41 +02:00
a3cc676ac6 Improved player spawn, closes #1890 2014-08-21 19:18:06 +02:00
db7222976e Code cleanup 2014-08-21 17:26:41 +02:00
e1ef86074e Merge pull request #1937 from Yosshi999/patch
Fixed #1923 sending NULL to Level::getXZ()
2014-08-20 16:03:52 +02:00
9f4582349d Fixed #1923 sending NULL to Level::getXZ() 2014-08-20 22:32:19 +09:00
5dc3fe4fe9 Fix backwards-incompatible change 2014-08-19 16:26:37 +02:00
8446bd2ba5 Added thread stop message 2014-08-19 12:55:21 +02:00
9f34d22013 Detach invalid Workers on shutdown 2014-08-19 12:46:44 +02:00
973d6b5869 Removed 'unhandled data packet' debug message 2014-08-19 12:30:12 +02:00
40d2f8a373 Save level data automatically, closes #1927 2014-08-19 11:54:12 +02:00
b66f49dc5e Fixed infinite recursion when setting a block on an EmptyChunkSection 2014-08-19 11:37:02 +02:00
5c150f696c Fixed task not being freed from player on close 2014-08-19 11:31:23 +02:00
0246648a2c Possible solution for #1703 in-game action lag 2014-08-18 23:25:46 +02:00
532b12c6c0 Mycelium spreads like grass and MonsterSpawner breaktime added 2014-08-18 20:06:18 +02:00
34711dc346 Fixed #1889 Players drop their inventory when they die 2014-08-18 14:49:53 +02:00
3c231118a6 Fixed #1674 Wooden tools only craft with Oak wood 2014-08-18 14:43:08 +02:00
a816234ee8 Merge pull request #1917 from Yosshi999/patch2
creative & survival hotbar bugfix
2014-08-18 14:33:05 +02:00
baa34a7cca creative & survival hotbar bugfix
:P
2014-08-18 21:18:14 +09:00
daf1a8266d Merge pull request #1906 from PocketMine/MoreEvents
Added more events, API 1.3.0
2014-08-18 13:55:35 +02:00
4e6ff81674 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-08-18 13:51:21 +02:00
84a1b319c8 Modified chunk generation garbage collector 2014-08-18 13:49:43 +02:00
16774e66e6 Fixed crashes when default level is not loaded 2014-08-18 13:42:20 +02:00
67b97ade8b Workaround crash when placing paintings 2014-08-18 13:36:59 +02:00
0f04f4bc8a creative & survival hotbar bugfix 2014-08-17 21:55:31 +09:00
4c7b172cbe creative & survival hotbar bugfix
Supports Air
Bug fix
2014-08-17 21:51:32 +09:00
e91781cbf2 EndPortal, EndStone, MonsterSpawner, Mycelium and Podzol blocks added 2014-08-17 02:00:17 +02:00
cf0dc95a76 Merge pull request #1910 from Falkirks/master
Improve behaviour of showPlayer()
2014-08-16 20:26:56 +02:00
9fa7b9b5ea Fixed indent 2014-08-16 11:03:40 -07:00
badbe75d58 Check if player is online before showing 2014-08-16 11:00:57 -07:00
5eee4f9771 Fixed AddEntityPacket, added base Arrow 2014-08-16 16:37:57 +02:00
52d28795fa Added Villager spawn egg 2014-08-16 14:25:58 +02:00
c675605014 Added item activation, zombie spawn egg 2014-08-16 14:01:07 +02:00
758a6af678 Added Chiseled stone brick, red sand, end stone 2014-08-16 13:34:58 +02:00
6f30cd8a22 Removed PHP_VERSION constant on pocketmine namespace 2014-08-16 13:17:05 +02:00
8455e89784 Bump API version to 1.3.0 2014-08-16 13:08:46 +02:00
eee0eb5458 Added RemoteServerCommandEvent 2014-08-16 13:05:20 +02:00
7e4a191593 Added SignChangeEvent 2014-08-16 12:58:16 +02:00
8725ad522f Remove player unset limitations 2014-08-16 12:47:19 +02:00
a610a86579 Fixed #1901, EmptyChunkSection gets replaced by invalid Section 2014-08-16 11:54:08 +02:00
24134a06b8 Alternate chunk generation between multiple levels 2014-08-16 11:49:37 +02:00
de6f5309dc Fixed #1882 Race-condition on multiple world generation, causing lock of the geneartion thread 2014-08-16 11:18:26 +02:00
a2e231101e Added extra information to CONTRIBUTING.md about issue titles 2014-08-16 10:58:41 +02:00
918024e466 Load later plugins with custom loader, fixes API 2014-08-16 00:30:37 +02:00
9e74169d74 Better Anvil chunk loading 2014-08-15 17:04:16 +02:00
ec93ed3e3d Fixed crash on tile unloading 2014-08-15 16:37:39 +02:00
a7b44e3892 Stop submission of plugin syntax error crashes 2014-08-15 16:18:54 +02:00
31b92b392e Throw invalid event exception when a plugin tries to declare an abstract event 2014-08-15 16:15:12 +02:00
2f9494ed52 Fixed crash caused by a race condition on Query 2014-08-15 16:07:04 +02:00
7a5c583407 Throw exception when null chunk is passed to a Tile/Entity 2014-08-15 16:04:48 +02:00
f60e2860e8 Release strong weak references on close, closes #1883 2014-08-15 13:41:13 +02:00
9c95441402 Force despawn of players on quit 2014-08-13 20:43:46 +02:00
1f902d814e Move only own player from eye level 2014-08-13 20:25:43 +02:00
0ab3da88be Send player movements as direct packets 2014-08-13 19:32:25 +02:00
e6edace944 Move players from eye level, not top of head 2014-08-13 19:26:45 +02:00
3ee61d5ebb Improved chunk cache, clean invalid chunks 2014-08-13 19:21:42 +02:00
19d391b9b2 Added Exception handling on level loading 2014-08-13 10:48:53 +02:00
e462a89189 Order chunks to be generated 2014-08-13 09:51:43 +02:00
d616e73242 Fixed chunk sending 2014-08-13 09:41:13 +02:00
5ec6ccefda Merge pull request #1875 from KnownUnown/patch-1
Fixed AddMobPacket's Type - (is now int)
2014-08-12 19:34:42 +02:00
58d7599d6f Fixed AddMobPacket's Type - (is now int)
Thanks @Intyre!
2014-08-12 12:31:07 -05:00
0c5f920dfd Level formats can send chunks without creating an AsyncTask, API 1.2.1 (small fix, no changes) 2014-08-12 17:39:39 +02:00
67f6482c76 Implemented circular chunk sending 2014-08-12 17:30:01 +02:00
7b141b0b73 Remove head offset from client-side MovePlayerPacket 2014-08-12 17:16:31 +02:00
b17ce16262 Fixed RCON usage 2014-08-10 18:35:01 +02:00
fee7f5060b Made AsyncTask::onCompletion() implementation optional 2014-08-10 18:15:06 +02:00
76cd164aa4 Fixed source servers getting invalid AutoUpdater notifications 2014-08-10 13:25:15 +02:00
582f1540a7 Players are now moved using the head, closes #1842 2014-08-10 13:22:12 +02:00
4d7c953572 Possible fix for 'Invalid Chunk given' crash 2014-08-10 13:09:41 +02:00
06c01f14c6 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-08-10 12:28:03 +02:00
c43431c921 Fixed #1826 Block damage values were swapped in McRegion 2014-08-10 12:27:49 +02:00
4e1805ae02 Merge pull request #1859 from PEMapModder/patch-2
Update CONTRIBUTING.md
2014-08-10 12:09:32 +02:00
ac34b9eda0 Update CONTRIBUTING.md
PocketMine namespaces are all in lowercase letters.
2014-08-10 18:08:09 +08:00
3495c79c0c Fixed crashes related to ChunkEvent 2014-08-09 10:42:03 +02:00
77799d8f3d Fixed AsyncWorker includes 2014-08-08 18:06:07 +02:00
dfdf9ddb45 Merge pull request #1846 from milo1000/issue_1843
Issue 1843 - RCON worker threads synchronization corrected
2014-08-08 16:26:47 +02:00
86d423ae4d Hide timezone guess errors 2014-08-08 12:53:31 +02:00
eff454d103 Fixed AsyncWorker not getting the proper path and not using the correct class 2014-08-08 11:51:36 +02:00
51120fdd4f Added ThreadManager, removed PHP self-kill 2014-08-08 11:36:55 +02:00
5242e87026 Issue 1843 - RCON worker threads synchronization corrected 2014-08-07 10:19:23 +02:00
269a10fadd Modified Level and Chunk deprecated methods 2014-08-06 16:22:55 +02:00
232bf5ebe4 Modified Chunk provider saving 2014-08-06 16:22:49 +02:00
2904aa06ef Merge pull request #1838 from PEMapModder/patch-2
Fixes Position::fromObject() $strong parameter neglected
2014-08-06 11:12:53 +02:00
e10c70e776 A typo fix 2014-08-06 11:06:30 +08:00
2cead226db Fixes Position::fromObject() $strong parameter neglected 2014-08-05 23:45:09 +08:00
2784925a5e Merge pull request #1822 from LukeDarling/patch-1
fixed tell command so itdoesn'tlooklikethisanymore
2014-08-03 22:38:21 +02:00
d2a14e8303 fixed tell command so itdoesn'tlooklikethisanymore 2014-08-03 13:22:41 -04:00
071033ad5c Added new installer languages 2014-08-02 18:00:36 +02:00
1e3ed8640c Updated Installer wizard language 2014-08-02 17:54:48 +02:00
60a576e541 Added proper Entity->__toString() 2014-08-02 17:48:56 +02:00
eee7e659e9 Added ChunkLoadEvent, ChunkUnloadEvent, ChunkPopulateEvent 2014-08-02 17:19:33 +02:00
7ddfd4394d Merge pull request #1818 from 64FF00/master
Added getExecutor() and setExecutor() method to PluginCommand
2014-08-02 14:43:12 +02:00
f0f2eb9a01 ... 2014-08-02 10:17:27 +09:00
839f6621eb Added getExecutor() and setExecutor() method to PluginCommand
:D
2014-08-02 10:11:36 +09:00
7fcaa78de4 Catch uncatched thrown Exceptions to get useful backtraces 2014-08-01 17:04:16 +02:00
915443b508 Disabled chunk ticking until it is stable 2014-08-01 15:25:40 +02:00
e17a7005a1 Throw exception on invalid chunk 2014-08-01 14:33:50 +02:00
c1846e3bcf Improved chunk serialization 2014-08-01 13:22:48 +02:00
81feff6d0d Merge pull request #1813 from PocketMine/revert-1748-enabled-builtin-php
Revert "Enabled built-in PHP"
2014-08-01 12:50:05 +02:00
9b84d8c248 Revert "Enabled built-in PHP" 2014-08-01 12:49:53 +02:00
26ec562fbf Added worlds directive to pocketmine.yml to load extra worlds or use a plugin-provided generator 2014-08-01 12:24:08 +02:00
d10274ca7c Improved memory usage when chunks are saved/generated 2014-08-01 11:53:24 +02:00
7c68e42a86 Fixed chunk rotation on McRegion-based worlds 2014-08-01 11:52:13 +02:00
171de939cd Fixed crash on chunks that are used by an entity after generation 2014-07-31 20:05:07 +02:00
58bded4988 Merge pull request #1801 from PocketMine/McRegion
Added multiple level formats support, implemented McRegion
2014-07-31 19:28:39 +02:00
cb4a970631 Tuned generator to use a better way to process chunks, closes #1807 #1794 #1740 #1741 #1685 2014-07-31 19:27:01 +02:00
95b5979351 Removed SimpleChunk from generator, core, use binary representation of chunks 2014-07-31 14:28:17 +02:00
18d13fdc32 Added threaded chunk sending for all formats 2014-07-31 10:19:44 +02:00
1a442b793c Fixed Tiles/Entities not using the correct chunk type 2014-07-30 18:24:59 +02:00
765d4f30c7 Added caching to non-converted network chunks 2014-07-30 17:30:22 +02:00
2eced89e6f Do not send crash reports generated from a source PM installation 2014-07-30 17:05:46 +02:00
293102d8c4 Fixed typo, BLockLight -> BlockLight 2014-07-30 16:59:52 +02:00
25f5d409f1 Fixed loading invalid plugins crashing the server 2014-07-30 16:57:31 +02:00
4128b22e85 Reuse McRegion classes on Anvil 2014-07-30 16:38:56 +02:00
487ce00542 Correctly fixed #1659 PvP settings not working 2014-07-30 16:07:21 +02:00
a9cd03da2e Changed @williamtdr syntax 2014-07-30 16:05:36 +02:00
f5fee4c909 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-07-30 14:10:39 +02:00
016b08ecf2 Added block order detection, added support for non-sectioned level formats 2014-07-30 12:57:00 +02:00
3515a037c5 Merge pull request #1804 from PocketMine/revert-1760-patch-1
Revert API breaking changes "Remove similar player name check from the beginning limit"
2014-07-30 00:36:12 +02:00
d6e413e8ca Revert "Remove similar player name check from the beginning limit" 2014-07-30 00:34:54 +02:00
f991efd5bc Merge pull request #1803 from Falkirks/patch-1
Spelling on crashDump()
2014-07-30 00:12:08 +02:00
913c116e7b Spelling 2014-07-29 15:10:50 -07:00
8fafb85784 Added proper chunk saving in McRegion 2014-07-29 19:36:41 +02:00
b0aad89e7a Fixed a few typos in McRegion 2014-07-29 19:11:09 +02:00
ce018fd7c8 Bumped API version to 1.2.0 (backwards-compatible changes, related to level formats) 2014-07-29 18:55:27 +02:00
afe44e6c6f Added setting to select the default level format 2014-07-29 18:54:40 +02:00
e9311f5ceb Added base McRegion classes 2014-07-29 18:43:52 +02:00
b2978133f7 Added McRegion detection to Anvil 2014-07-29 17:21:07 +02:00
6b331535c6 Merge pull request #1748 from MinecrafterJPN/enabled-builtin-php
Enabled built-in PHP
2014-07-29 09:56:05 +02:00
3370052fac Do not send crash reports from non-phar plugins 2014-07-28 23:14:29 +02:00
7d8a961374 Throw exception when an invalid chunk is set as the parent of a Tile/Entity 2014-07-28 21:40:50 +02:00
e97139919a Added new exception when a plugin creates an orphaned PluginTask 2014-07-28 20:28:50 +02:00
81faddafb0 Fixed crash when using Level scheduled block update ReversePriorityQueue 2014-07-28 19:18:28 +02:00
d0936329aa Fixed crash reports using invalid lastError data 2014-07-28 15:41:13 +02:00
9124513584 Added RakLib version to crash information 2014-07-28 14:48:26 +02:00
e860c339e2 Fixed crash when cactus was updated 2014-07-28 14:46:52 +02:00
10c67a57a7 Added extra crash dump settings, added way to disable parts of it or change the host 2014-07-28 14:42:51 +02:00
b10e63b951 Removed debug values on Crash dump 2014-07-28 13:47:38 +02:00
409eeda6ee Added plugin crash detection 2014-07-28 13:20:13 +02:00
bf09c48d62 Fixed build number on crash dumps 2014-07-28 12:57:08 +02:00
aac646d343 Fixed full path phar on logs 2014-07-28 12:20:16 +02:00
ed90d58e32 Fixed crash when placing water or lava 2014-07-28 12:18:17 +02:00
e219f4784c Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-07-28 12:12:14 +02:00
b5a1c23c50 Moved rtfd documentation 2014-07-28 12:11:01 +02:00
14817df2c7 Merge pull request #1793 from Intyre/bug/inventory
player creative inventory bugfix
2014-07-28 11:36:32 +02:00
cc87064915 player creative inventory bugfix 2014-07-28 02:24:08 +02:00
aded24e6c6 Updated error path replace (again\!) 2014-07-27 23:05:49 +02:00
a95f8b45f1 Updated error path replace 2014-07-27 22:55:45 +02:00
7a3703d8b1 Fixed undefined $fullFile on CrashDump 2014-07-27 21:25:24 +02:00
ca59546ace Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-07-27 21:01:06 +02:00
2330f363bd Fix for thrown EmptyChunkSection modification exception 2014-07-27 20:54:28 +02:00
042861b51f Merge pull request #1790 from RobertClarke/patch-1
Small typo fix on main language file
2014-07-27 18:40:04 +02:00
98f42a936e Small typo fix 2014-07-27 17:36:40 +01:00
6d77b0883e Fixed getTrace() on crash with xdebug 2014-07-27 17:31:39 +02:00
f53d513894 Merge pull request #1789 from PocketMine/CrashDump
Added Crash Dumps and automatic reporting
2014-07-27 15:26:36 +02:00
e6e15ceffa Fixed typo in crash text 2014-07-27 14:09:34 +02:00
9d75baf212 Added automatic reporting 2014-07-27 14:00:00 +02:00
7b45df680e Added time and plugin cause 2014-07-27 12:39:38 +02:00
f93d5339bc Use correct syntax 2014-07-26 17:06:22 +02:00
677071e7cb Merge pull request #1782 from Yosshi999/master
Updated Stick crafting recipe to give x4
2014-07-26 16:22:12 +02:00
4fa6fb0546 Updated Stick crafting recipe to give x4 2014-07-26 22:48:41 +09:00
0ca614a2c3 Merge pull request #1781 from Intyre/versionbump
Support for MCPE v0.9.5
2014-07-26 15:47:59 +02:00
bdfa6c0bc5 link to docs added to README 2014-07-26 15:08:48 +02:00
ccb7e86cf1 changed version and protocol to support v0.9.5 2014-07-26 15:07:32 +02:00
03a970e91f Merge pull request #1777 from Striker209MPE/patch-5
Fixed an error related to AIR constant
2014-07-25 07:51:27 -05:00
b3e9bb8fec Fixed an error related to AIR constant
A E_NOTICE error happened: "Use of undefined constant AIR - assumed 'AIR'"

should be fixed
2014-07-25 11:44:08 +02:00
48b99486b0 Merge pull request #1775 from Intyre/docs
docs for pocketmine-mp.readthedocs.org
2014-07-25 07:03:06 +02:00
6921e6f2aa docs for pocketmine-mp.readthedocs.org 2014-07-25 06:58:57 +02:00
987f54ba08 Edit syntax to confirm with rest of document. 2014-07-24 15:13:12 -05:00
09ef1f1721 Merge pull request #1772 from Striker209MPE/patch-3
Fixed error with useBreakOn parameters
2014-07-24 15:11:59 -05:00
3eae7a1875 Fixed error with useBreakOn parameters
A E_RECOVERABLE_ERROR error happened: "Argument 1 passed to pocketmine\block\Block::getDrops() must be an instance of pocketmine\item\Item, null given

AND

A E_RECOVERABLE_ERROR error happened: "Argument 1 passed to pocketmine\block\Generic::onBreak() must be an instance of pocketmine\item\Item, null given

are fixed
2014-07-24 22:10:33 +02:00
21587ae3eb Merge pull request #1760 from PEMapModder/patch-1
Allow player names contained in existing online player list.
2014-07-23 09:48:11 -05:00
e5337d8949 Make Fire check more efficent - by @Tschrock 2014-07-23 09:46:30 -05:00
c92a1ba7fe Release similar player name check from the beginning
For example, some would like to write `map` for `pemapmodder`, and this is what existed in amai beetroot when we used `SQLite3::query("SELECT ... ALIKE")`.
2014-07-23 22:33:45 +08:00
2066e92f84 Revert "Proper Fire ID checking. Fix #1756."
This reverts commit cd943f52a1.
2014-07-23 09:08:18 -05:00
cd943f52a1 Proper Fire ID checking. Fix #1756. 2014-07-23 08:58:26 -05:00
c3424beda9 Revert "Update Level.php"
This reverts commit da9dfabae4.
2014-07-22 13:59:23 -05:00
b6506d1db8 Revert "Corrected parameters for setBlock()"
This reverts commit 2f3a011ed3.
2014-07-22 13:59:16 -05:00
4cec3e7e37 Merge pull request #1749 from Falkirks/patch-1
Fixed fire issue
2014-07-22 13:29:12 -05:00
2f3a011ed3 Corrected parameters for setBlock() 2014-07-22 07:05:13 -07:00
da9dfabae4 Update Level.php 2014-07-21 18:15:54 -07:00
4c83e9bb56 Update Level.php 2014-07-21 20:04:58 -05:00
090d159766 Enabled built-in PHP 2014-07-22 09:46:47 +09:00
14d86339fc Fixed previous error. 2014-07-21 18:27:50 -05:00
ccf34a9db8 #1745 part 2! 2014-07-21 15:29:40 -05:00
97af1b6008 Fix #1745 2014-07-21 13:02:24 -05:00
16d33b01f4 Fix #1663 2014-07-21 10:51:30 -05:00
fa318ce706 Merge pull request #1736 from swagking47/patch-5
Fix unintentional typo in InventoryTransactionEvent.php.
2014-07-21 10:15:19 -05:00
accea03d52 Merge pull request #1741 from PEMapModder/patch-6
Added count(Enum)
2014-07-21 10:10:40 -05:00
adcdf650a3 Added count(Enum) 2014-07-21 19:25:20 +08:00
e8e825322b Update InventoryTransactionEvent.php 2014-07-20 15:28:53 -04:00
1b36b10520 Merge pull request #1729 from PEMapModder/patch-5
Fixed wrong doccomment for Vector3::add()
2014-07-19 10:32:16 +02:00
0d37e96678 Fixed wrong doccomment for Vector3::add()
Yes I know it was me who wrote it wrong.
2014-07-19 11:59:31 +08:00
2448405e3a Fixed rcon password being shown 2014-07-18 11:58:39 +02:00
2e773a32ff Removed crash() 2014-07-18 11:55:24 +02:00
d8cba4f045 Implemented new crash dumps 2014-07-18 11:54:11 +02:00
07c1ed1c36 Moved pthreads check before its usage 2014-07-18 10:49:38 +02:00
d6711125a9 Bumped MCPE version to v0.9.4 2014-07-18 10:44:14 +02:00
b8802edd6d Only allow one thread per property, fixes #1668 2014-07-17 21:22:48 +02:00
71bf984e9e Better fix for shared STONE constant, closes #1711 2014-07-17 21:20:15 +02:00
9c9d786194 Fix #1659 2014-07-16 13:07:26 -05:00
bd2cb4b851 Fixed #1614, possible solution for #1678 2014-07-15 13:17:29 +02:00
6e77901453 Fixed inventory being sent before spawning 2014-07-14 16:54:29 +02:00
ebe8a902e5 Fixed being killed on teleport 2014-07-14 15:55:16 +02:00
304524f6d8 Fixed crash on /stop 2014-07-14 14:41:19 +02:00
cb879977d2 Use Player::getDisplayName() on more commands 2014-07-14 14:12:03 +02:00
096e238242 Fixed #1628 invalid sender x,y,z on /spawnpoint, closes #1671 2014-07-14 14:07:43 +02:00
f2d5daffc0 Whoops, Markdown spacing issue 2014-07-14 20:23:46 +09:30
12275125d2 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-07-14 12:48:09 +02:00
3d3b6826e4 Merge pull request #1669 from sekjun9878/master
Android issues to the correct repo @PEMapModder
2014-07-14 20:18:20 +09:30
3a8adfe2b8 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-07-14 12:47:34 +02:00
14116b6730 Android issues to the correct repo @PEMapModder 2014-07-14 20:17:30 +09:30
241d3d72af Merge pull request #1664 from sekjun9878/master
Issue Tracking Guidelines
2014-07-14 12:47:11 +02:00
79e864f4f1 Added far-generated loaded chunk to garbage collection 2014-07-14 12:46:03 +02:00
7812a3c4fc Added Won't Fix and Invalid as per @shoghicp's suggestion. Renamed PR: RFC to PR: Contribution 2014-07-14 20:15:26 +09:30
dbe5e9b4e9 Remove informal language from Contributing Guidelines 2014-07-14 17:25:28 +09:30
d743888b8d Issue Tracking Guidelines 2014-07-14 17:11:25 +09:30
0db009b08f Improved chunk generation queue 2014-07-14 03:10:25 +02:00
7cdf5a73eb Bumped MCPE version to 0.9.1 2014-07-14 02:21:04 +02:00
6c442551f7 Fixed client crashing (temp.), fixed clients not spawning. (Fixes #1640 #1636 #1590 #1573) 2014-07-14 02:19:14 +02:00
eccd82ca4b Moved player attack filter from Living to Player 2014-07-13 19:04:00 +02:00
6fbfa1836f Merge branch 'master' of https://github.com/PocketMine/PocketMine-MP 2014-07-13 22:04:41 +09:30
5dfb1fb9d5 Fix bug where a double quote would show when kick reason is not specified. 2014-07-13 22:03:54 +09:30
4a615f03b5 Merge pull request #1649 from PEMapModder/patch-2
Added doccomment for Vector3::add() and Vector3::subtract()
2014-07-13 12:26:46 +02:00
47503d84c2 Added doccomment for Vector3::add() and Vector3::subtract()
This is to avoid IDEs thinking that argument 1 for `Vector3::subtract()` must be an int. (But the fact is `Vector3` is OK too)
2014-07-13 13:43:09 +08:00
fdb7fa36b8 Fixed #1641 2014-07-13 01:10:16 +02:00
e29ddadd2f Fixed #1642 2014-07-13 01:04:10 +02:00
d2ed0aa9f0 Merge pull request #1634 from PocketMine/timings
Implemented Timings
2014-07-12 19:30:41 +02:00
a7944502cd Added small things 2014-07-12 19:27:51 +02:00
063d14ba63 Merge pull request #1638 from KnownUnown/master
Fix formality mistake
2014-07-12 18:42:11 +02:00
35ea9708a5 Fix formality mistake
Contractions such as "I've" should not be used in formal writing.
2014-07-12 11:36:03 -05:00
9a4ead54e3 Added more timings 2014-07-12 15:23:06 +02:00
0d55d5c653 Fixed typo 2014-07-12 14:36:22 +02:00
94bc817756 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-07-12 14:18:12 +02:00
52b0e8b1ee Updated RakLib, fixes random upload increase 2014-07-12 14:17:35 +02:00
9bdd294a66 Implemented global, tasks timings 2014-07-12 14:09:29 +02:00
0bfa9506d1 Updated API version to 1.1.0 (backwards-compatible) 2014-07-12 02:26:41 +02:00
67b0c4bc2e Added base timings 2014-07-12 02:26:06 +02:00
dd729ced68 Revert "Possible fix for #1628"
This reverts commit a6e22de6a3.
2014-07-11 10:21:58 -05:00
a6e22de6a3 Possible fix for #1628 2014-07-11 10:19:28 -05:00
7624eda7b1 Update damage sources for creative mode players 2014-07-11 16:24:04 +02:00
5e47dda0a8 Enable death through void, suicide 2014-07-11 09:18:15 -05:00
61043d2e0d Fix #1615
Players in creative cannot die from non-magic (plugin/console) causes.
2014-07-11 09:14:49 -05:00
3e882ef40d Revert "Fix #1615"
This reverts commit a8359f29a8.
2014-07-11 09:12:19 -05:00
a8359f29a8 Fix #1615
Players in creative cannot die from non-magic (plugin/console) causes.
2014-07-11 09:07:24 -05:00
167ee97569 Fix kick command broadcast message. 2014-07-11 22:14:57 +09:30
53214005cd Kick message reflects Vanila MCPC not Bukkit 2014-07-11 22:05:50 +09:30
6e74bb7faf Kick reason grammar 2014-07-11 21:52:57 +09:30
f60fdb5e61 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-07-11 12:47:19 +02:00
4bd2f3aea8 Use the world spawn by default for players, fixes #1616 2014-07-11 12:45:43 +02:00
dcba580115 Merge pull request #1626 from PEMapModder/patch-2
Fix #1622 /kick on unknown players crashes the server
2014-07-11 12:16:44 +02:00
63008c4ebb Fix #1622 2014-07-11 17:24:25 +08:00
c16f45ce39 Fixed unsigned fields being read as signed 2014-07-11 02:55:29 +02:00
f2fa13119a Added upload/download speed on title bar, referenced ChunkRequestTask 2014-07-11 02:23:40 +02:00
756a8fead6 Fixed #1604 2014-07-11 01:34:49 +02:00
7ed6ac2341 Fixed #1609 2014-07-11 01:18:37 +02:00
4a072b4163 Better chunk unload queues 2014-07-11 01:15:52 +02:00
91b2f81f3c Updated RakLib version 2014-07-11 00:53:48 +02:00
5c826cb9ab Fixed /list not showing the proper player count 2014-07-10 20:40:56 +02:00
20b0df4b57 Added deprecation warning on plugin events 2014-07-10 17:39:20 +02:00
1fab6bd589 Added settings.query-plugins setting 2014-07-10 17:24:12 +02:00
7dd4a843c6 Fixed #1598 spawning on a index-corrupted Anvil chunk 2014-07-10 16:52:59 +02:00
828f7f1590 Fall damage is now working 2014-07-10 16:16:11 +02:00
c9535162bd Added more damage sources 2014-07-10 14:02:56 +02:00
99c5ad789b Improved entity attack push 2014-07-10 13:29:29 +02:00
e6c510e7fd Fixed #1595 Undefined variable on QueryHandler 2014-07-10 13:15:24 +02:00
d3789d4fed Fixed /kick player name 2014-07-10 13:05:15 +02:00
8fbc63c14e Fixed /kill player name 2014-07-10 13:05:04 +02:00
4d0b184ca4 Fixed #1591, handle player disconnect and level change killing 2014-07-10 12:35:19 +02:00
589fde27c0 Reorder chunk unloading to leave chunks in memory for the GC time before removal 2014-07-10 01:32:18 +02:00
6cb55da9c7 Added correct save parameters to chunk unloading 2014-07-10 01:30:59 +02:00
0251ae93d8 Fixed #1578 Chunk garbage collection not marking chunks as unused 2014-07-10 01:17:51 +02:00
5b69f07a55 Tuned CPU usage on main lop and RakLib 2014-07-09 23:39:25 +02:00
9604907566 Fixed #1584 duplicated death messages 2014-07-09 20:25:40 +02:00
1f882f42d3 Save and restore entity health 2014-07-09 20:23:58 +02:00
981796fd4c Fixed #1583 not repeated Tasks getting repeated 2014-07-09 20:07:35 +02:00
3e53ecdfb3 Merge pull request #1585 from PEMapModder/master
Let plugin enable/disable events extend PluginEvent
2014-07-09 19:28:13 +02:00
cd324c3247 Let plugin enable/disable events extend PluginEvent 2014-07-10 00:40:16 +08:00
99d4ff5bdb Merge remote-tracking branch 'origin/master' 2014-07-09 18:43:33 +09:30
88bcaea292 Fixes #1570. Removed isValidPharFilename check as the function is very unreliable. 2014-07-09 18:42:57 +09:30
ff90b83a9f Merge pull request #1581 from PEMapModder/patch-1
Update cause of lava and fire damage
2014-07-09 16:38:12 +09:30
f3079f8444 Update cause of lava and fire damage 2014-07-09 14:40:50 +08:00
304 changed files with 7518 additions and 6349 deletions

6
.gitignore vendored
View File

@ -20,4 +20,8 @@ Desktop.ini
# Mac crap
.DS_Store
/nbproject/private/
/nbproject/private/
# Sphinx-doc
/docs/build/
!/docs/requirements.txt

3
.gitmodules vendored
View File

@ -6,3 +6,6 @@
path = src/raklib
url = https://github.com/PocketMine/RakLib.git
branch = master
[submodule "src/spl"]
path = src/spl
url = https://github.com/PocketMine/PocketMine-SPL.git

View File

@ -2,36 +2,37 @@
# PocketMine-MP Contribution Guidelines
Before contributing to PocketMine-MP, please read this. Also, take a look if your contribution fits the PocketMine-MP goals below.
You must follow these guidelines if you wish to contribute to the PocketMine-MP code base, or participate in issue tracking.
## I've a question
## I have a question
* For questions, please refer to the _#pocketmine_ or _#mcpedevs_ IRC channel on Freenode. There is a [WebIRC](http://webchat.freenode.net?channels=pocketmine,mcpedevs&uio=d4) if you want.
* You can ask directly to _[@PocketMine](https://twitter.com/PocketMine)_ in Twitter, but don't expect an inmediate reply.
* You can ask directly to _[@PocketMine](https://twitter.com/PocketMine)_ in Twitter, but don't expect an immediate reply.
* You may use our [Forum](http://forums.pocketmine.net) to ask questions.
* We do not accept questions or support requests in our issue tracker.
## I want to create an issue
* First, use the [Issue Search](https://github.com/PocketMine/PocketMine-MP/search?ref=cmdform&type=Issues) to check if anyone has reported it.
* Is your issue related to a Plugin? If so, please contact their original author instead of reporting it here.
* And no, we won't update a Plugin because you need it.
* When reporting, give as much info as you can, and if the Issue is a crash, give the Crash Dump.
* Issues should be written in English.
## Creating an Issue
- First, use the [Issue Search](https://github.com/PocketMine/PocketMine-MP/search?ref=cmdform&type=Issues) to check if anyone has reported it.
- If your issue is related to a plugin, you must contact their original author instead of reporting it here.
- If your issue is related to a PocketMine official plugin, or our Android application, you must create an issue on that specific repository.
- **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.
- **No generic titles** such as "Question", "Help", "Crash Report" etc. If an issue has a generic title they will either be closed on the spot, or a collaborator will edit it to describe the actual symptom.
- Information must be provided in the issue body, not in the title. No tags are allowed in the title, and do not change the title if the issue has been solved.
- Similarly, no generic issue reports. It is the issue submitter'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.
## I want a new feature / I want to contribute code
## Contributing Code
* Use the [Pull Request](https://github.com/PocketMine/PocketMine-MP/pull/new) system, your request will be checked and discussed.
* __Create a single branch for that pull request__
* If you want to be part of PocketMine-MP, we will ask you to.
* Code using the 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
* __No merge commits are allowed, or multiple features per pull request__
**Thanks for contributing to PocketMine-MP!**
__Thanks for contributing to PocketMine-MP!__
### Code syntax
### 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.
* 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 after them.
* Code MUST use tabs for indenting.
@ -45,7 +46,7 @@ It is mainly [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accept
```php
<?php
namespace pocketmine\Example;
namespace pocketmine\example;
class ExampleClass{
const EXAMPLE_CLASS_CONSTANT = 1;
@ -71,3 +72,55 @@ class ExampleClass{
}
```
## 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.
PocketMine-MP uses GitHub Issues Labels. There are a total of 12 labels.
Note: For future reference, labels must not be longer than 15 letters.
#### Categories
Category labels are prefixed by `C:`. Multiple category labels may be applied to a single issue(but try to keep this to a minimum and do not overuse category labels).
- C: Core - This label is applied when the bug results in a fatal crash, or is related to neither Gameplay nor Plugin API.
- C: Gameplay - This label is applied when the bug effects the gameplay.
- C: API - This label is applied when the bug effects the Plugin API.
#### Pull Requests
Pull Requests are prefixed by `PR:`. Only one label may be applied for a Pull Request.
- PR: Bug Fix - This label is applied when the Pull Request fixes a bug.
- PR: Contribution - This label is applied when the Pull Request contributes code to PocketMine-MP such as a new feature or an improvement.
#### Status
Status labels show the status of the issue. Multiple status labels may be applied.
- Reproduced - This label is applied when the bug has been reproduced, or 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.
- Debugged - This label is applied when the cause of the bug has been found.
- Priority - This label is applied when the bug is easy to fix, or if the scale of the bug is global.
- Won't Fix - This label is applied if the bug has been decided not be fixed for some reason. e.g. when the bug benefits gameplay. *This label may only be applied to a closed issue.*
#### Miscellaneous
Miscellaneous labels are labels that show status not related to debugging that bug. The To-Do label and the Mojang label may not be applied to a single issue at the same time.
- To-Do - This label is applied when the issue is not a bug, but a feature request or a list of features to be implemented that count towards a milestone.
- Mojang - This label is applied when the issue is suspected of being caused by the Minecraft: Pocket Edition client, but has not been confirmed.
- Invalid - This label is applied when the issue is reporting a false bug that works as intended, a support request, etc. *This label may only be applied to a closed issue.*
### 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:
```
Alpha_<version_number> [release_title][release_version]
```
For example:
```
Alpha_1.4 beta2
```

View File

@ -21,6 +21,8 @@ __PocketMine-MP is a free, open-source software that creates Minecraft: Pocket E
### [Forums](http://forums.pocketmine.net/)
### [Documentation](http://pocketmine-mp.readthedocs.org/)
### [Plugin Repository](http://plugins.pocketmine.net/)
<!--## [FAQ: Frequently Asked Questions](https://github.com/PocketMine/PocketMine-MP/wiki/Frequently-Asked-Questions)-->

View File

@ -30,78 +30,78 @@ abstract class Achievement{
/**
* @var array[]
*/
public static $list = array(
public static $list = [
/*"openInventory" => array(
"name" => "Taking Inventory",
"requires" => [],
),*/
"mineWood" => array(
"mineWood" => [
"name" => "Getting Wood",
"requires" => array( //"openInventory",
),
),
"buildWorkBench" => array(
"requires" => [ //"openInventory",
],
],
"buildWorkBench" => [
"name" => "Benchmarking",
"requires" => array(
"requires" => [
"mineWood",
),
),
"buildPickaxe" => array(
],
],
"buildPickaxe" => [
"name" => "Time to Mine!",
"requires" => array(
"requires" => [
"buildWorkBench",
),
),
"buildFurnace" => array(
],
],
"buildFurnace" => [
"name" => "Hot Topic",
"requires" => array(
"requires" => [
"buildPickaxe",
),
),
"acquireIron" => array(
],
],
"acquireIron" => [
"name" => "Acquire hardware",
"requires" => array(
"requires" => [
"buildFurnace",
),
),
"buildHoe" => array(
],
],
"buildHoe" => [
"name" => "Time to Farm!",
"requires" => array(
"requires" => [
"buildWorkBench",
),
),
"makeBread" => array(
],
],
"makeBread" => [
"name" => "Bake Bread",
"requires" => array(
"requires" => [
"buildHoe",
),
),
"bakeCake" => array(
],
],
"bakeCake" => [
"name" => "The Lie",
"requires" => array(
"requires" => [
"buildHoe",
),
),
"buildBetterPickaxe" => array(
],
],
"buildBetterPickaxe" => [
"name" => "Getting an Upgrade",
"requires" => array(
"requires" => [
"buildPickaxe",
),
),
"buildSword" => array(
],
],
"buildSword" => [
"name" => "Time to Strike!",
"requires" => array(
"requires" => [
"buildWorkBench",
),
),
"diamonds" => array(
],
],
"diamonds" => [
"name" => "DIAMONDS!",
"requires" => array(
"requires" => [
"acquireIron",
),
),
],
],
);
];
public static function broadcast(Player $player, $achievementId){
@ -120,10 +120,10 @@ abstract class Achievement{
public static function add($achievementId, $achievementName, array $requires = []){
if(!isset(Achievement::$list[$achievementId])){
Achievement::$list[$achievementId] = array(
Achievement::$list[$achievementId] = [
"name" => $achievementName,
"requires" => $requires,
);
];
return true;
}

View File

@ -19,12 +19,14 @@
*
*/
interface LoggerAttachment{
namespace pocketmine;
class CompatibleClassLoader extends \BaseClassLoader{
/**
* @param mixed $level
* @param string $message
* @deprecated
*/
public function log($level, $message);
public function add($namespace, $paths){
$this->addPath(array_shift($paths));
}
}

View File

@ -0,0 +1,247 @@
<?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
*
*
*/
namespace pocketmine;
use pocketmine\network\protocol\Info;
use pocketmine\plugin\PluginLoadOrder;
use pocketmine\utils\Utils;
use pocketmine\utils\VersionString;
use raklib\RakLib;
class CrashDump{
/** @var Server */
private $server;
private $fp;
private $time;
private $data = [];
private $encodedData = null;
private $path;
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";
$this->fp = fopen($this->path, "wb");
$this->data["time"] = $this->time;
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", $this->time));
$this->addLine();
$this->baseCrash();
$this->generalData();
$this->pluginsData();
$this->extraData();
$this->encodeData();
}
public function getPath(){
return $this->path;
}
public function getEncodedData(){
return $this->encodedData;
}
public function getData(){
return $this->data;
}
private function encodeData(){
$this->addLine();
$this->addLine("----------------------REPORT THE DATA BELOW THIS LINE-----------------------");
$this->addLine();
$this->addLine("===BEGIN CRASH DUMP===");
$this->encodedData = zlib_encode(json_encode($this->data, JSON_UNESCAPED_SLASHES), ZLIB_ENCODING_DEFLATE, 9);
foreach(str_split(base64_encode($this->encodedData), 76) as $line){
$this->addLine($line);
}
$this->addLine("===END CRASH DUMP===");
}
private function pluginsData(){
if(class_exists("pocketmine\\plugin\\PluginManager", false)){
$this->addLine();
$this->addLine("Loaded plugins:");
$this->data["plugins"] = [];
foreach($this->server->getPluginManager()->getPlugins() as $p){
$d = $p->getDescription();
$this->data["plugins"][$d->getName()] = [
"name" => $d->getName(),
"version" => $d->getVersion(),
"authors" => $d->getAuthors(),
"api" => $d->getCompatibleApis(),
"enabled" => $p->isEnabled(),
"depends" => $d->getDepend(),
"softDepends" => $d->getSoftDepend(),
"main" => $d->getMain(),
"load" => $d->getOrder() === PluginLoadOrder::POSTWORLD ? "POSTWORLD" : "STARTUP",
"website" => $d->getWebsite()
];
$this->addLine($d->getName() . " " . $d->getVersion() . " by " . implode(", ", $d->getAuthors()) . " for API(s) " . implode(", ", $d->getCompatibleApis()));
}
}
}
private function extraData(){
global $arguments;
if($this->server->getProperty("auto-report.send-settings", true) !== false){
$this->data["parameters"] = (array) $arguments;
$this->data["server.properties"] = @file_get_contents($this->server->getDataPath() . "server.properties");
$this->data["server.properties"] = preg_replace("#^rcon\\.password=(.*)$#m", "rcon.password=******", $this->data["server.properties"]);
$this->data["pocketmine.yml"] = @file_get_contents($this->server->getDataPath() . "pocketmine.yml");
}else{
$this->data["pocketmine.yml"] = "";
$this->data["server.properties"] = "";
$this->data["parameters"] = [];
}
$extensions = [];
foreach(get_loaded_extensions() as $ext){
$extensions[$ext] = phpversion($ext);
}
$this->data["extensions"] = $extensions;
if($this->server->getProperty("auto-report.send-phpinfo", true) !== false){
ob_start();
phpinfo();
$this->data["phpinfo"] = ob_get_contents();
ob_end_clean();
}
}
private function baseCrash(){
global $lastExceptionError, $lastError;
if(isset($lastExceptionError)){
$error = $lastExceptionError;
}else{
$error = (array) error_get_last();
$error["trace"] = getTrace(4);
$errorConversion = [
E_ERROR => "E_ERROR",
E_WARNING => "E_WARNING",
E_PARSE => "E_PARSE",
E_NOTICE => "E_NOTICE",
E_CORE_ERROR => "E_CORE_ERROR",
E_CORE_WARNING => "E_CORE_WARNING",
E_COMPILE_ERROR => "E_COMPILE_ERROR",
E_COMPILE_WARNING => "E_COMPILE_WARNING",
E_USER_ERROR => "E_USER_ERROR",
E_USER_WARNING => "E_USER_WARNING",
E_USER_NOTICE => "E_USER_NOTICE",
E_STRICT => "E_STRICT",
E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
E_DEPRECATED => "E_DEPRECATED",
E_USER_DEPRECATED => "E_USER_DEPRECATED",
];
$error["fullFile"] = $error["file"];
$error["file"] = cleanPath($error["file"]);
$error["type"] = isset($errorConversion[$error["type"]]) ? $errorConversion[$error["type"]] : $error["type"];
if(($pos = strpos($error["message"], "\n")) !== false){
$error["message"] = substr($error["message"], 0, $pos);
}
}
if(isset($lastError)){
$this->data["lastError"] = $lastError;
}
$this->data["error"] = $error;
unset($this->data["error"]["fullFile"]);
unset($this->data["error"]["trace"]);
$this->addLine("Error: " . $error["message"]);
$this->addLine("File: " . $error["file"]);
$this->addLine("Line: " . $error["line"]);
$this->addLine("Type: " . $error["type"]);
if(strpos($error["file"], "src/pocketmine/") === false and strpos($error["file"], "src/raklib/") === false and file_exists($error["fullFile"])){
$this->addLine();
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
$this->data["plugin"] = true;
$reflection = new \ReflectionClass("pocketmine\\plugin\\PluginBase");
$file = $reflection->getProperty("file");
$file->setAccessible(true);
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
$filePath = \pocketmine\cleanPath($file->getValue($plugin));
if(strpos($error["file"], $filePath) === 0){
$this->data["plugin"] = $plugin->getName();
$this->addLine("BAD PLUGIN: " . $plugin->getDescription()->getFullName());
break;
}
}
}else{
$this->data["plugin"] = false;
}
$this->addLine();
$this->addLine("Code:");
$this->data["code"] = [];
if($this->server->getProperty("auto-report.send-code", true) !== false){
$file = @file($error["fullFile"], FILE_IGNORE_NEW_LINES);
for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10; ++$l){
$this->addLine("[" . ($l + 1) . "] " . @$file[$l]);
$this->data["code"][$l + 1] = @$file[$l];
}
}
$this->addLine();
$this->addLine("Backtrace:");
foreach(($this->data["trace"] = $error["trace"]) as $line){
$this->addLine($line);
}
$this->addLine();
}
private function generalData(){
$version = new VersionString();
$this->data["general"] = [];
$this->data["general"]["version"] = $version->get(false);
$this->data["general"]["build"] = $version->getBuild();
$this->data["general"]["protocol"] = Info::CURRENT_PROTOCOL;
$this->data["general"]["api"] = \pocketmine\API_VERSION;
$this->data["general"]["git"] = \pocketmine\GIT_COMMIT;
$this->data["general"]["raklib"] = RakLib::VERSION;
$this->data["general"]["uname"] = php_uname("a");
$this->data["general"]["php"] = phpversion();
$this->data["general"]["zend"] = zend_version();
$this->data["general"]["php_os"] = PHP_OS;
$this->data["general"]["os"] = Utils::getOS();
$this->addLine("PocketMine-MP version: " . $version->get(false) . " #" . $version->getNumber() . " [Protocol " . Info::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
$this->addLine("Git commit: " . GIT_COMMIT);
$this->addLine("uname -a: " . php_uname("a"));
$this->addLine("PHP Version: " . phpversion());
$this->addLine("Zend version: " . zend_version());
$this->addLine("OS : " . PHP_OS . ", " . Utils::getOS());
}
public function addLine($line = ""){
fwrite($this->fp, $line . PHP_EOL);
}
public function add($str){
fwrite($this->fp, $str);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -68,16 +68,14 @@ namespace pocketmine {
use LogLevel;
use pocketmine\utils\Binary;
use pocketmine\utils\MainLogger;
use pocketmine\utils\TextFormat;
use pocketmine\utils\Utils;
use pocketmine\wizard\Installer;
use raklib\RakLib;
const VERSION = "Alpha_1.4dev";
const API_VERSION = "1.0.0";
const API_VERSION = "1.3.1";
const CODENAME = "絶好(Zekkou)ケーキ(Cake)";
const MINECRAFT_VERSION = "v0.9.0 alpha";
const PHP_VERSION = "5.5";
const MINECRAFT_VERSION = "v0.9.5 alpha";
if(\Phar::running(true) !== ""){
@define("pocketmine\\PATH", \Phar::running(true) . "/");
@ -85,16 +83,21 @@ namespace pocketmine {
@define("pocketmine\\PATH", \getcwd() . DIRECTORY_SEPARATOR);
}
if(!class_exists("SplClassLoader", false)){
require_once(\pocketmine\PATH . "src/spl/SplClassLoader.php");
if(!extension_loaded("pthreads")){
echo "[CRITICAL] Unable to find the pthreads extension." . PHP_EOL;
echo "[CRITICAL] Please use the installer provided on the homepage." . PHP_EOL;
exit(1);
}
$autoloader = new \SplClassLoader();
$autoloader->setMode(\SplAutoloader::MODE_DEBUG);
$autoloader->add("pocketmine", [
\pocketmine\PATH . "src"
]);
if(!class_exists("ClassLoader", false)){
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->addPath(\pocketmine\PATH . "src");
$autoloader->addPath(\pocketmine\PATH . "src" . DIRECTORY_SEPARATOR . "spl");
$autoloader->register(true);
if(!class_exists("raklib\\RakLib", false)){
require(\pocketmine\PATH . "src/raklib/raklib/RakLib.php");
@ -112,14 +115,14 @@ namespace pocketmine {
$time -= $time % 60;
//TODO: Parse different time & date formats by region. ¬¬ world
//Example: USA
exec("time.exe /T", $hour);
@exec("time.exe /T", $hour);
$i = array_map("intval", explode(":", trim($hour[0])));
exec("date.exe /T", $date);
@exec("date.exe /T", $date);
$j = array_map("intval", explode(substr($date[0], 2, 1), trim($date[0])));
$offset = round((mktime($i[0], $i[1], 0, $j[1], $j[0], $j[2]) - $time) / 60) * 60;
$offset = @round((mktime($i[0], $i[1], 0, $j[1], $j[0], $j[2]) - $time) / 60) * 60;
}else{
exec("date +%s", $t);
$offset = round((intval(trim($t[0])) - time()) / 60) * 60;
@exec("date +%s", $t);
$offset = @round((intval(trim($t[0])) - time()) / 60) * 60;
}
$daylight = (int) date("I");
@ -136,16 +139,16 @@ namespace pocketmine {
}
gc_enable();
error_reporting(E_ALL | E_STRICT);
error_reporting(-1);
ini_set("allow_url_fopen", 1);
ini_set("display_errors", 1);
ini_set("display_startup_errors", 1);
ini_set("default_charset", "utf-8");
ini_set("memory_limit", "128M"); //Default
ini_set("memory_limit", "256M"); //Default
define("pocketmine\\START_TIME", microtime(true));
$opts = getopt("", array("enable-ansi", "disable-ansi", "data:", "plugins:", "no-wizard"));
$opts = getopt("", ["enable-ansi", "disable-ansi", "data:", "plugins:", "no-wizard", "enable-profiler"]);
define("pocketmine\\DATA", isset($opts["data"]) ? realpath($opts["data"]) . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR);
define("pocketmine\\PLUGIN_PATH", isset($opts["plugins"]) ? realpath($opts["plugins"]) . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
@ -154,6 +157,15 @@ namespace pocketmine {
$logger = new MainLogger(\pocketmine\DATA . "server.log", \pocketmine\ANSI);
if(isset($opts["enable-profiler"])){
if(function_exists("profiler_enable")){
\profiler_enable();
$logger->notice("Execution is being profiled");
}else{
$logger->notice("No profiler found. Please install https://github.com/krakjoe/profiler");
}
}
function kill($pid){
switch(Utils::getOS()){
case "win":
@ -166,29 +178,46 @@ namespace pocketmine {
}
}
function getTrace($start = 1){
$e = new \Exception();
$trace = $e->getTrace();
function getTrace($start = 1, $trace = null){
if($trace === null){
if(function_exists("xdebug_get_function_stack")){
$trace = array_reverse(xdebug_get_function_stack());
}else{
$e = new \Exception();
$trace = $e->getTrace();
}
}
$messages = [];
$j = 0;
for($i = (int) $start; isset($trace[$i]); ++$i, ++$j){
$params = "";
if(isset($trace[$i]["args"])){
foreach($trace[$i]["args"] as $name => $value){
if(isset($trace[$i]["args"]) or isset($trace[$i]["params"])){
if(isset($trace[$i]["args"])){
$args = $trace[$i]["args"];
}else{
$args = $trace[$i]["params"];
}
foreach($args as $name => $value){
$params .= (is_object($value) ? get_class($value) . " " . (method_exists($value, "__toString") ? $value->__toString() : "object") : gettype($value) . " " . @strval($value)) . ", ";
}
}
$messages[] = "#$j " . (isset($trace[$i]["file"]) ? $trace[$i]["file"] : "") . "(" . (isset($trace[$i]["line"]) ? $trace[$i]["line"] : "") . "): " . (isset($trace[$i]["class"]) ? $trace[$i]["class"] . $trace[$i]["type"] : "") . $trace[$i]["function"] . "(" . substr($params, 0, -2) . ")";
$messages[] = "#$j " . (isset($trace[$i]["file"]) ? cleanPath($trace[$i]["file"]) : "") . "(" . (isset($trace[$i]["line"]) ? $trace[$i]["line"] : "") . "): " . (isset($trace[$i]["class"]) ? $trace[$i]["class"] . (($trace[$i]["type"] === "dynamic" or $trace[$i]["type"] === "->") ? "->" : "::") : "") . $trace[$i]["function"] . "(" . substr($params, 0, -2) . ")";
}
return $messages;
}
function error_handler($errno, $errstr, $errfile, $errline){
function cleanPath($path){
return rtrim(str_replace(["\\", ".php", "phar://", rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), "/"), rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH), "/")], ["/", "", "", "", ""], $path), "/");
}
function error_handler($errno, $errstr, $errfile, $errline, $trace = null){
global $lastError;
if(error_reporting() === 0){ //@ error-control
return false;
}
$errorConversion = array(
$errorConversion = [
E_ERROR => "E_ERROR",
E_WARNING => "E_WARNING",
E_PARSE => "E_PARSE",
@ -204,14 +233,28 @@ namespace pocketmine {
E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
E_DEPRECATED => "E_DEPRECATED",
E_USER_DEPRECATED => "E_USER_DEPRECATED",
);
];
$type = ($errno === E_ERROR or $errno === E_WARNING or $errno === E_USER_ERROR or $errno === E_USER_WARNING) ? LogLevel::ERROR : LogLevel::NOTICE;
$errno = isset($errorConversion[$errno]) ? $errorConversion[$errno] : $errno;
if(($pos = strpos($errstr, "\n")) !== false){
$errstr = substr($errstr, 0, $pos);
}
$logger = MainLogger::getLogger();
$logger->log($type, "A $errno error happened: \"$errstr\" in \"$errfile\" at line $errline");
foreach(getTrace() as $i => $line){
$oldFile = $errfile;
$errfile = cleanPath($errfile);
$logger->log($type, "An $errno error happened: \"$errstr\" in \"$errfile\" at line $errline");
foreach(($trace = getTrace($trace === null ? 3 : 0, $trace)) as $i => $line){
$logger->debug($line);
}
$lastError = [
"type" => $type,
"message" => $errstr,
"fullFile" => $oldFile,
"file" => $errfile,
"line" => $errline,
"trace" => $trace
];
return true;
}
@ -220,8 +263,8 @@ namespace pocketmine {
$errors = 0;
if(version_compare("5.4.0", PHP_VERSION) > 0){
$logger->critical("Use PHP >= 5.4.0");
if(version_compare("5.6.0", PHP_VERSION) > 0){
$logger->critical("You must use PHP >= 5.6");
++$errors;
}
@ -235,18 +278,13 @@ namespace pocketmine {
++$errors;
}
if(!extension_loaded("pthreads")){
$logger->critical("Unable to find the pthreads extension.");
$pthreads_version = phpversion("pthreads");
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
if(version_compare($pthreads_version, "2.0.4") < 0){
$logger->critical("pthreads >= 2.0.4 is required, while you have $pthreads_version.");
++$errors;
}else{
$pthreads_version = phpversion("pthreads");
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
if(version_compare($pthreads_version, "2.0.4") < 0){
$logger->critical("pthreads >= 2.0.4 is required, while you have $pthreads_version.");
++$errors;
}
}
if(!extension_loaded("uopz")){
@ -313,12 +351,36 @@ namespace pocketmine {
$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);
$server->start();
$logger->info("Stopping other threads");
foreach(ThreadManager::getInstance()->getAll() as $id => $thread){
if($thread->isRunning()){
$logger->debug("Stopping " . (new \ReflectionClass($thread))->getShortName() . " thread");
if($thread instanceof Thread){
$thread->kill();
if($thread->isRunning() or !$thread->join()){
$thread->detach();
}
}elseif($thread instanceof Worker){
$thread->kill();
sleep(1);
if($thread->isRunning() or !$thread->join()){
$thread->detach();
}
}
}elseif(!$thread->isJoined()){
$logger->debug("Joining " . (new \ReflectionClass($thread))->getShortName() . " thread");
$thread->join();
}
}
$logger->shutdown();
$logger->join();
kill(getmypid());
exit(0);
}

View File

@ -36,6 +36,8 @@ use pocketmine\event\HandlerList;
use pocketmine\event\level\LevelInitEvent;
use pocketmine\event\level\LevelLoadEvent;
use pocketmine\event\server\ServerCommandEvent;
use pocketmine\event\Timings;
use pocketmine\event\TimingsHandler;
use pocketmine\inventory\CraftingManager;
use pocketmine\inventory\InventoryType;
use pocketmine\inventory\Recipe;
@ -58,7 +60,6 @@ use pocketmine\nbt\tag\Long;
use pocketmine\nbt\tag\Short;
use pocketmine\nbt\tag\String;
use pocketmine\network\protocol\DataPacket;
use pocketmine\network\protocol\Info;
use pocketmine\network\query\QueryHandler;
use pocketmine\network\query\QueryPacket;
use pocketmine\network\RakLibInterface;
@ -67,6 +68,7 @@ use pocketmine\network\SourceInterface;
use pocketmine\network\upnp\UPnP;
use pocketmine\permission\BanList;
use pocketmine\permission\DefaultPermissions;
use pocketmine\plugin\PharPluginLoader;
use pocketmine\plugin\Plugin;
use pocketmine\plugin\PluginLoadOrder;
use pocketmine\plugin\PluginManager;
@ -273,7 +275,7 @@ class Server{
* @return int
*/
public function getViewDistance(){
return min(11, max($this->getConfigInt("view-distance", 7), 4));
return max(56, $this->getProperty("chunk-sending.max-chunks"));
}
/**
@ -453,7 +455,7 @@ class Server{
}
/**
* @return \SplClassLoader
* @return \ClassLoader
*/
public function getLoader(){
return $this->autoloader;
@ -624,39 +626,39 @@ class Server{
$path = $this->getDataPath() . "players/";
if(!file_exists($path . "$name.dat")){
$spawn = $this->getDefaultLevel()->getSafeSpawn();
$nbt = new Compound(false, array(
$nbt = new Compound(false, [
new Long("firstPlayed", floor(microtime(true) * 1000)),
new Long("lastPlayed", floor(microtime(true) * 1000)),
new Enum("Pos", array(
new Enum("Pos", [
new Double(0, $spawn->x),
new Double(1, $spawn->y),
new Double(2, $spawn->z)
)),
]),
new String("Level", $this->getDefaultLevel()->getName()),
new String("SpawnLevel", $this->getDefaultLevel()->getName()),
new Int("SpawnX", (int) $spawn->x),
new Int("SpawnY", (int) $spawn->y),
new Int("SpawnZ", (int) $spawn->z),
new Byte("SpawnForced", 1), //TODO
//new String("SpawnLevel", $this->getDefaultLevel()->getName()),
//new Int("SpawnX", (int) $spawn->x),
//new Int("SpawnY", (int) $spawn->y),
//new Int("SpawnZ", (int) $spawn->z),
//new Byte("SpawnForced", 1), //TODO
new Enum("Inventory", []),
new Compound("Achievements", []),
new Int("playerGameType", $this->getGamemode()),
new Enum("Motion", array(
new Enum("Motion", [
new Double(0, 0.0),
new Double(1, 0.0),
new Double(2, 0.0)
)),
new Enum("Rotation", array(
]),
new Enum("Rotation", [
new Float(0, 0.0),
new Float(1, 0.0)
)),
]),
new Float("FallDistance", 0.0),
new Short("Fire", 0),
new Short("Air", 0),
new Byte("OnGround", 1),
new Byte("Invulnerable", 0),
new String("NameTag", $name),
));
]);
$nbt->Pos->setTagType(NBT::TAG_Double);
$nbt->Inventory->setTagType(NBT::TAG_Compound);
$nbt->Motion->setTagType(NBT::TAG_Double);
@ -676,35 +678,35 @@ class Server{
$this->logger->notice("Old Player data found for \"" . $name . "\", upgrading profile");
foreach($data->get("inventory") as $slot => $item){
if(count($item) === 3){
$nbt->Inventory[$slot + 9] = new Compound(false, array(
$nbt->Inventory[$slot + 9] = new Compound(false, [
new Short("id", $item[0]),
new Short("Damage", $item[1]),
new Byte("Count", $item[2]),
new Byte("Slot", $slot + 9),
new Byte("TrueSlot", $slot + 9)
));
]);
}
}
foreach($data->get("hotbar") as $slot => $itemSlot){
if(isset($nbt->Inventory[$itemSlot + 9])){
$item = $nbt->Inventory[$itemSlot + 9];
$nbt->Inventory[$slot] = new Compound(false, array(
new Short("id", $item->id),
new Short("Damage", $item->Damage),
new Byte("Count", $item->Count),
$nbt->Inventory[$slot] = new Compound(false, [
new Short("id", $item["id"]),
new Short("Damage", $item["Damage"]),
new Byte("Count", $item["Count"]),
new Byte("Slot", $slot),
new Byte("TrueSlot", $item->TrueSlot)
));
new Byte("TrueSlot", $item["TrueSlot"])
]);
}
}
foreach($data->get("armor") as $slot => $item){
if(count($item) === 2){
$nbt->Inventory[$slot + 100] = new Compound(false, array(
$nbt->Inventory[$slot + 100] = new Compound(false, [
new Short("id", $item[0]),
new Short("Damage", $item[1]),
new Byte("Count", 1),
new Byte("Slot", $slot + 100)
));
]);
}
}
foreach($data->get("achievements") as $achievement => $status){
@ -786,7 +788,7 @@ class Server{
$matchedPlayers = [];
foreach($this->getOnlinePlayers() as $player){
if(strtolower($player->getName()) === $partialName){
$matchedPlayers = array($player);
$matchedPlayers = [$player];
break;
}elseif(stripos($player->getName(), $partialName) !== false){
$matchedPlayers[] = $player;
@ -800,9 +802,7 @@ class Server{
* @param Player $player
*/
public function removePlayer(Player $player){
if($player->isOnline() === false){
unset($this->players[$player->getAddress() . ":" . $player->getPort()]);
}
unset($this->players[$player->getAddress() . ":" . $player->getPort()]);
}
/**
@ -878,6 +878,7 @@ class Server{
public function unloadLevel(Level $level, $forceUnload = false){
if($level->unload($forceUnload) === true and $this->isLevelLoaded($level->getFolderName())){
unset($this->levels[$level->getID()]);
return true;
}
@ -910,7 +911,7 @@ class Server{
$provider = LevelProviderManager::getProvider($path);
if($provider === null){
$this->logger->error("Could not load level \"" . $name . "\"");
$this->logger->error("Could not load level \"" . $name . "\": Unknown provider");
return false;
}
@ -919,7 +920,14 @@ class Server{
// @rename($path . "tileEntities.yml", $path . "tiles.yml");
//}
$level = new Level($this, $name, $path, $provider);
try{
$level = new Level($this, $name, $path, $provider);
}catch(\Exception $e){
$this->logger->error("Could not load level \"" . $name . "\": " . $e->getMessage());
return false;
}
$this->levels[$level->getID()] = $level;
$this->getPluginManager()->callEvent(new LevelLoadEvent($level));
@ -1030,7 +1038,7 @@ class Server{
*
* @return bool
*/
public function generateLevel($name, $seed = null, $generator = null, array $options = []){
public function generateLevel($name, $seed = null, $generator = null, $options = []){
if(trim($name) === "" or $this->isLevelGenerated($name)){
return false;
}
@ -1048,7 +1056,9 @@ class Server{
}
}
$provider = "pocketmine\\level\\format\\anvil\\Anvil";
if(($provider = LevelProviderManager::getProviderByName($providerName = $this->getProperty("level-settings.default-format", "mcregion"))) === null){
$provider = LevelProviderManager::getProviderByName($providerName = "mcregion");
}
$path = $this->getDataPath() . "worlds/" . $name . "/";
/** @var \pocketmine\level\format\LevelProvider $provider */
@ -1061,12 +1071,39 @@ class Server{
$this->getPluginManager()->callEvent(new LevelLoadEvent($level));
for($Z = 5; $Z <= 11; ++$Z){
for($X = 5; $X <= 11; ++$X){
$level->generateChunk($X, $Z);
$this->getLogger()->notice("Spawn terrain for level \"$name\" is being generated in the background");
$radiusSquared = ($this->getViewDistance() + 1) / M_PI;
$radius = ceil(sqrt($radiusSquared));
$centerX = $level->getSpawn()->getX() >> 4;
$centerZ = $level->getSpawn()->getZ() >> 4;
$order = [];
for($X = -$radius; $X <= $radius; ++$X){
for($Z = -$radius; $Z <= $radius; ++$Z){
$distance = ($X * $X) + ($Z * $Z);
if($distance > $radiusSquared){
continue;
}
$chunkX = $X + $centerX;
$chunkZ = $Z + $centerZ;
$index = Level::chunkHash($chunkX, $chunkZ);
$order[$index] = $distance;
}
}
asort($order);
$chunkX = $chunkZ = null;
foreach($order as $index => $distance){
Level::getXZ($index, $chunkX, $chunkZ);
$level->generateChunk($chunkX, $chunkZ);
}
return true;
}
@ -1105,7 +1142,7 @@ class Server{
* @return string
*/
public function getConfigString($variable, $defaultValue = ""){
$v = getopt("", array("$variable::"));
$v = getopt("", ["$variable::"]);
if(isset($v[$variable])){
return (string) $v[$variable];
}
@ -1155,7 +1192,7 @@ class Server{
* @return int
*/
public function getConfigInt($variable, $defaultValue = 0){
$v = getopt("", array("$variable::"));
$v = getopt("", ["$variable::"]);
if(isset($v[$variable])){
return (int) $v[$variable];
}
@ -1178,7 +1215,7 @@ class Server{
* @return boolean
*/
public function getConfigBoolean($variable, $defaultValue = false){
$v = getopt("", array("$variable::"));
$v = getopt("", ["$variable::"]);
if(isset($v[$variable])){
$value = $v[$variable];
}else{
@ -1340,13 +1377,13 @@ class Server{
}
/**
* @param \SplClassLoader $autoloader
* @param \ClassLoader $autoloader
* @param \ThreadedLogger $logger
* @param string $filePath
* @param string $dataPath
* @param string $pluginPath
*/
public function __construct(\SplClassLoader $autoloader, \ThreadedLogger $logger, $filePath, $dataPath, $pluginPath){
public function __construct(\ClassLoader $autoloader, \ThreadedLogger $logger, $filePath, $dataPath, $pluginPath){
self::$instance = $this;
$this->autoloader = $autoloader;
@ -1354,7 +1391,7 @@ class Server{
$this->filePath = $filePath;
$this->dataPath = $dataPath;
$this->pluginPath = $pluginPath;
@mkdir($this->dataPath . "worlds/", 0777);
@mkdir($this->dataPath . "worlds/", 0777, true);
@mkdir($this->dataPath . "players/", 0777);
@mkdir($this->pluginPath, 0777);
@ -1390,14 +1427,13 @@ class Server{
$this->config = new Config($this->dataPath . "pocketmine.yml", Config::YAML, []);
$this->logger->info("Loading server properties...");
$this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, array(
$this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, [
"motd" => "Minecraft: PE Server",
"server-port" => 19132,
"memory-limit" => "256M",
"white-list" => false,
"announce-player-achievements" => true,
"spawn-protection" => 16,
"view-distance" => 8,
"max-players" => 20,
"allow-flight" => false,
"spawn-animals" => true,
@ -1415,34 +1451,34 @@ class Server{
"enable-rcon" => false,
"rcon.password" => substr(base64_encode(Utils::getRandomBytes(20, false)), 3, 10),
"auto-save" => true,
));
]);
ServerScheduler::$WORKERS = $this->getProperty("settings.async-workers", ServerScheduler::$WORKERS);
$this->scheduler = new ServerScheduler();
if($this->getConfigBoolean("enable-rcon", false) === true){
$this->rcon = new RCON($this->getConfigString("rcon.password", ""), $this->getConfigInt("rcon.port", $this->getPort()), ($ip = $this->getIp()) != "" ? $ip : "0.0.0.0", $this->getConfigInt("rcon.threads", 1), $this->getConfigInt("rcon.clients-per-thread", 50));
$this->rcon = new RCON($this, $this->getConfigString("rcon.password", ""), $this->getConfigInt("rcon.port", $this->getPort()), ($ip = $this->getIp()) != "" ? $ip : "0.0.0.0", $this->getConfigInt("rcon.threads", 1), $this->getConfigInt("rcon.clients-per-thread", 50));
}
$this->maxPlayers = $this->getConfigInt("max-players", 20);
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "128M")))) !== false){
$value = array("M" => 1, "G" => 1024);
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "256M")))) !== false){
$value = ["M" => 1, "G" => 1024];
$real = ((int) substr($memory, 0, -1)) * $value[substr($memory, -1)];
if($real < 128){
$this->logger->warning("PocketMine-MP may not work right with less than 128MB of RAM", true, true, 0);
$this->logger->warning($this->getName() . " may not work right with less than 128MB of RAM", true, true, 0);
}
@ini_set("memory_limit", $memory);
}else{
$this->setConfigString("memory-limit", "128M");
$this->setConfigString("memory-limit", "256M");
}
if($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3){
$this->setConfigInt("difficulty", 3);
}
define("pocketmine\\DEBUG", $this->getProperty("debug.level", 1));
define("pocketmine\\DEBUG", (int) $this->getProperty("debug.level", 1));
if($this->logger instanceof MainLogger){
$this->logger->setLogDebug(\pocketmine\DEBUG > 1);
}
@ -1453,8 +1489,8 @@ class Server{
Level::$COMPRESSION_LEVEL = $this->getProperty("chunk-sending.compression-level", 7);
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0 and function_exists("cli_set_process_title")){
@cli_set_process_title("PocketMine-MP " . $this->getPocketMineVersion());
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0){
@cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion());
}
$this->logger->info("Starting Minecraft PE server on " . ($this->getIp() === "" ? "*" : $this->getIp()) . ":" . $this->getPort());
@ -1463,8 +1499,8 @@ class Server{
$this->addInterface($this->mainInterface = new RakLibInterface($this));
$this->logger->info("This server is running PocketMine-MP version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(false) . TextFormat::RESET . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0);
$this->logger->info("PocketMine-MP is distributed under the LGPL License", true, true, 0);
$this->logger->info("This server is running " . $this->getName() . " version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(false) . TextFormat::RESET . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0);
$this->logger->info($this->getName() . " is distributed under the LGPL License", true, true, 0);
$this->consoleSender = new ConsoleCommandSender();
$this->commandMap = new SimpleCommandMap($this);
@ -1474,9 +1510,18 @@ class Server{
Item::init();
$this->craftingManager = new CraftingManager();
PluginManager::$pluginParentTimer = new TimingsHandler("** Plugins");
Timings::init();
$this->pluginManager = new PluginManager($this, $this->commandMap);
$this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender);
$this->pluginManager->setUseTimings($this->getProperty("settings.enable-profiling", false));
$this->pluginManager->registerInterface("pocketmine\\plugin\\PharPluginLoader");
set_exception_handler([$this, "exceptionHandler"]);
register_shutdown_function([$this, "crashDump"]);
register_shutdown_function([$this, "forceShutdown"]);
$this->pluginManager->loadPlugins($this->pluginPath);
$this->updater = new AutoUpdater($this, $this->getProperty("auto-updater.host", "www.pocketmine.net"));
@ -1486,12 +1531,30 @@ class Server{
$this->generationManager = new GenerationRequestManager($this);
LevelProviderManager::addProvider($this, "pocketmine\\level\\format\\anvil\\Anvil");
LevelProviderManager::addProvider($this, "pocketmine\\level\\format\\mcregion\\McRegion");
Generator::addGenerator("pocketmine\\level\\generator\\Flat", "flat");
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "normal");
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "default");
foreach($this->getProperty("worlds", []) as $name => $worldSetting){
if($this->loadLevel($name) === false){
$seed = $this->getProperty("worlds.$name.seed", time());
$options = explode(":", $this->getProperty("worlds.$name.generator", Generator::getGenerator("default")));
$generator = Generator::getGenerator(array_shift($options));
if(count($options) > 0){
$options = [
"preset" => implode(":", $options),
];
}else{
$options = [];
}
$this->generateLevel($name, $seed, $generator, $options);
}
}
if($this->getDefaultLevel() === null){
$default = $this->getConfigString("level-name", "world");
if(trim($default) == ""){
@ -1510,17 +1573,25 @@ class Server{
$this->properties->save();
if(!($this->getDefaultLevel() instanceof Level)){
$this->getLogger()->emergency("No default level has been loaded");
$this->forceShutdown();
return;
}
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask("pocketmine\\utils\\Cache::cleanup"), $this->getProperty("ticks-per.cache-cleanup", 900), $this->getProperty("ticks-per.cache-cleanup", 900));
if($this->getConfigBoolean("auto-save", true) === true and $this->getProperty("ticks-per.autosave", 6000) > 0){
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "doAutoSave")), $this->getProperty("ticks-per.autosave", 6000), $this->getProperty("ticks-per.autosave", 6000));
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([$this, "doAutoSave"]), $this->getProperty("ticks-per.autosave", 6000), $this->getProperty("ticks-per.autosave", 6000));
}
if($this->getProperty("chunk-gc.period-in-ticks", 600) > 0){
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "doLevelGC")), $this->getProperty("chunk-gc.period-in-ticks", 600), $this->getProperty("chunk-gc.period-in-ticks", 600));
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([$this, "doLevelGC"]), $this->getProperty("chunk-gc.period-in-ticks", 600), $this->getProperty("chunk-gc.period-in-ticks", 600));
}
$this->enablePlugins(PluginLoadOrder::POSTWORLD);
$this->start();
}
/**
@ -1552,8 +1623,9 @@ class Server{
foreach($recipients as $recipient){
$recipient->sendMessage($message);
}
return count($recipients);
}
}
/**
* Broadcasts a Minecraft packet to a list of players
@ -1574,7 +1646,7 @@ class Server{
public function enablePlugins($type){
foreach($this->pluginManager->getPlugins() as $plugin){
if(!$plugin->isEnabled() and $plugin->getDescription()->getOrder() === $type){
$this->loadPlugin($plugin);
$this->enablePlugin($plugin);
}
}
@ -1587,19 +1659,32 @@ class Server{
/**
* @param Plugin $plugin
*/
public function loadPlugin(Plugin $plugin){
public function enablePlugin(Plugin $plugin){
$this->pluginManager->enablePlugin($plugin);
}
/**
* @param Plugin $plugin
*
* @deprecated
*/
public function loadPlugin(Plugin $plugin){
$this->enablePlugin($plugin);
}
public function disablePlugins(){
$this->pluginManager->disablePlugins();
}
public function checkConsole(){
Timings::$serverCommandTimer->startTiming();
if(($line = $this->console->getLine()) !== null){
$this->pluginManager->callEvent($ev = new ServerCommandEvent($this->consoleSender, $line));
$this->dispatchCommand($this->consoleSender, $ev->getCommand());
if(!$ev->isCancelled()){
$this->dispatchCommand($ev->getSender(), $ev->getCommand());
}
}
Timings::$serverCommandTimer->stopTiming();
}
/**
@ -1640,14 +1725,14 @@ class Server{
$this->maxPlayers = $this->getConfigInt("max-players", 20);
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "256M")))) !== false){
$value = array("M" => 1, "G" => 1024);
$value = ["M" => 1, "G" => 1024];
$real = ((int) substr($memory, 0, -1)) * $value[substr($memory, -1)];
if($real < 256){
$this->logger->warning("PocketMine-MP may not work right with less than 256MB of RAM", true, true, 0);
$this->logger->warning($this->getName() . " may not work right with less than 256MB of RAM", true, true, 0);
}
@ini_set("memory_limit", $memory);
}else{
$this->setConfigString("memory-limit", "128M");
$this->setConfigString("memory-limit", "256M");
}
if($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3){
@ -1664,6 +1749,7 @@ class Server{
$this->pluginManager->loadPlugins($this->pluginPath);
$this->enablePlugins(PluginLoadOrder::STARTUP);
$this->enablePlugins(PluginLoadOrder::POSTWORLD);
TimingsHandler::reload();
}
/**
@ -1671,6 +1757,7 @@ class Server{
*/
public function shutdown(){
$this->isRunning = false;
gc_collect_cycles();
}
public function forceShutdown(){
@ -1693,7 +1780,10 @@ class Server{
foreach($this->getLevels() as $level){
$this->unloadLevel($level, true);
}
$this->generationManager->shutdown();
if($this->generationManager instanceof GenerationRequestManager){
$this->generationManager->shutdown();
}
HandlerList::unregisterAll();
$this->scheduler->cancelAllTasks();
@ -1719,7 +1809,7 @@ class Server{
if($this->getProperty("settings.send-usage", true) !== false){
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "sendUsage")), 6000, 6000);
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([$this, "sendUsage"]), 6000, 6000);
$this->sendUsage();
}
@ -1731,44 +1821,26 @@ class Server{
$this->tickCounter = 0;
//register_shutdown_function(array($this, "dumpError"));
register_shutdown_function(array($this, "forceShutdown"));
if(function_exists("pcntl_signal")){
pcntl_signal(SIGTERM, array($this, "shutdown"));
pcntl_signal(SIGINT, array($this, "shutdown"));
pcntl_signal(SIGHUP, array($this, "shutdown"));
pcntl_signal(SIGTERM, [$this, "handleSignal"]);
pcntl_signal(SIGINT, [$this, "handleSignal"]);
pcntl_signal(SIGHUP, [$this, "handleSignal"]);
$this->getScheduler()->scheduleRepeatingTask(new CallbackTask("pcntl_signal_dispatch"), 5);
}
$this->logger->info("Default game type: " . self::getGamemodeString($this->getGamemode())); //TODO: string name
$this->logger->info("Done (" . round(microtime(true) - \pocketmine\START_TIME, 3) . 's)! For help, type "help" or "?"');
if(Utils::getOS() === "win"){ //Workaround less usleep() waste
$this->tickProcessorWindows();
}else{
$this->tickProcessor();
}
$this->tickProcessor();
$this->forceShutdown();
gc_collect_cycles();
}
private function tickProcessorWindows(){
$lastLoop = 0;
while($this->isRunning){
foreach($this->interfaces as $interface){
if($interface->process()){
$lastLoop = 0;
}
}
$this->generationManager->handlePackets();
if(($ticks = $this->tick()) !== true){
++$lastLoop;
if($lastLoop > 128){
usleep(1000);
}
}else{
$lastLoop = 0;
}
public function handleSignal($signo){
if($signo === SIGTERM or $signo === SIGINT or $signo === SIGHUP){
$this->shutdown();
}
}
@ -1788,113 +1860,87 @@ class Server{
}
}
public function dumpError(){
//TODO
if($this->stop === true){
public function exceptionHandler(\Exception $e){
if($e === null){
return;
}
error_handler(E_ERROR, $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTrace());
global $lastExceptionError, $lastError;
$lastExceptionError = $lastError;
$this->crashDump();
$this->forceShutdown();
kill(getmypid());
exit(1);
}
public function crashDump(){
if($this->isRunning === false){
return;
}
ini_set("memory_limit", "-1"); //Fix error dump not dumped on memory problems
$this->logger->emergency("An unrecoverable has occurred and the server has crashed. Creating an error dump");
$dump = "```\r\n# PocketMine-MP Error Dump " . date("D M j H:i:s T Y") . "\r\n";
$er = error_get_last();
$errorConversion = array(
E_ERROR => "E_ERROR",
E_WARNING => "E_WARNING",
E_PARSE => "E_PARSE",
E_NOTICE => "E_NOTICE",
E_CORE_ERROR => "E_CORE_ERROR",
E_CORE_WARNING => "E_CORE_WARNING",
E_COMPILE_ERROR => "E_COMPILE_ERROR",
E_COMPILE_WARNING => "E_COMPILE_WARNING",
E_USER_ERROR => "E_USER_ERROR",
E_USER_WARNING => "E_USER_WARNING",
E_USER_NOTICE => "E_USER_NOTICE",
E_STRICT => "E_STRICT",
E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
E_DEPRECATED => "E_DEPRECATED",
E_USER_DEPRECATED => "E_USER_DEPRECATED",
);
$er["type"] = isset($errorConversion[$er["type"]]) ? $errorConversion[$er["type"]] : $er["type"];
$dump .= "Error: " . var_export($er, true) . "\r\n\r\n";
if(stripos($er["file"], "plugin") !== false){
$dump .= "THIS ERROR WAS CAUSED BY A PLUGIN. REPORT IT TO THE PLUGIN DEVELOPER.\r\n";
}
$this->logger->emergency("An unrecoverable error has occurred and the server has crashed. Creating a crash dump");
$dump = new CrashDump($this);
$dump .= "Code: \r\n";
$file = @file($er["file"], FILE_IGNORE_NEW_LINES);
for($l = max(0, $er["line"] - 10); $l < $er["line"] + 10; ++$l){
$dump .= "[" . ($l + 1) . "] " . @$file[$l] . "\r\n";
}
$dump .= "\r\n\r\n";
$dump .= "Backtrace: \r\n";
foreach(getTrace() as $line){
$dump .= "$line\r\n";
}
$dump .= "\r\n\r\n";
$version = new VersionString();
$dump .= "PocketMine-MP version: " . $version->get(false). " #" . $version->getNumber() . " [Protocol " . Info::CURRENT_PROTOCOL . "; API " . API_VERSION . "]\r\n";
$dump .= "Git commit: " . GIT_COMMIT . "\r\n";
$dump .= "uname -a: " . php_uname("a") . "\r\n";
$dump .= "PHP Version: " . phpversion() . "\r\n";
$dump .= "Zend version: " . zend_version() . "\r\n";
$dump .= "OS : " . PHP_OS . ", " . Utils::getOS() . "\r\n";
$dump .= "Debug Info: " . var_export($this->debugInfo(false), true) . "\r\n\r\n\r\n";
global $arguments;
$dump .= "Parameters: " . var_export($arguments, true) . "\r\n\r\n\r\n";
$p = $this->api->getProperties();
if($p["rcon.password"] != ""){
$p["rcon.password"] = "******";
}
$dump .= "server.properties: " . var_export($p, true) . "\r\n\r\n\r\n";
if(class_exists("pocketmine\\plugin\\PluginManager", false)){
$dump .= "Loaded plugins:\r\n";
foreach($this->getPluginManager()->getPlugins() as $p){
$d = $p->getDescription();
$dump .= $d->getName() . " " . $d->getVersion() . " by " . implode(", ", $d->getAuthors()) . "\r\n";
$this->logger->emergency("Please submit the \"" . $dump->getPath() . "\" file to the Bug Reporting page. Give as much info as you can.");
if($this->getProperty("auto-report.enabled", true) !== false){
$plugin = $dump->getData()["plugin"];
if(is_string($plugin)){
$p = $this->pluginManager->getPlugin($plugin);
if($p instanceof Plugin and !($p->getPluginLoader() instanceof PharPluginLoader)){
return;
}
}elseif(\Phar::running(true) == ""){
return;
}elseif($dump->getData()["type"] === "E_PARSE" or $dump->getData()["type"] === "E_COMPILE_ERROR"){
return;
}
$reply = Utils::postURL("http://" . $this->getProperty("auto-report.host", "crash.pocketmine.net") . "/submit/api", [
"report" => "yes",
"name" => $this->getName() . " " . $this->getPocketMineVersion(),
"email" => "crash@pocketmine.net",
"reportPaste" => base64_encode($dump->getEncodedData())
]);
if(($data = json_decode($reply)) !== false and isset($data->crashId)){
$reportId = $data->crashId;
$reportUrl = $data->crashUrl;
$this->logger->emergency("The crash dump has been automatically submitted to the Crash Archive. You can view it on $reportUrl or use the ID #$reportId.");
}
$dump .= "\r\n\r\n";
}
$extensions = [];
foreach(get_loaded_extensions() as $ext){
$extensions[$ext] = phpversion($ext);
}
//$this->checkMemory();
//$dump .= "Memory Usage Tracking: \r\n" . chunk_split(base64_encode(gzdeflate(implode(";", $this->memoryStats), 9))) . "\r\n";
$dump .= "Loaded Modules: " . var_export($extensions, true) . "\r\n";
$this->checkMemory();
$dump .= "Memory Usage Tracking: \r\n" . chunk_split(base64_encode(gzdeflate(implode(";", $this->memoryStats), 9))) . "\r\n";
ob_start();
phpinfo();
$dump .= "\r\nphpinfo(): \r\n" . chunk_split(base64_encode(gzdeflate(ob_get_contents(), 9))) . "\r\n";
ob_end_clean();
$dump .= "\r\n```";
$name = "Error_Dump_" . date("D_M_j-H.i.s-T_Y");
//log($dump, $name, true, 0, true);
$this->logger->emergency("Please submit the \"{$name}.log\" file to the Bug Reporting page. Give as much info as you can.", true, true, 0);
}
private function tickProcessor(){
$lastLoop = 0;
$connectionTimer = Timings::$connectionTimer;
while($this->isRunning){
$connectionTimer->startTiming();
foreach($this->interfaces as $interface){
if($interface->process()){
$lastLoop = 0;
}
}
$connectionTimer->stopTiming();
$this->generationManager->handlePackets();
++$lastLoop;
if(($ticks = $this->tick()) !== true){
++$lastLoop;
if($lastLoop > 16 and $lastLoop < 128){
usleep(200);
}elseif($lastLoop < 512){
usleep(400);
}else{
if($lastLoop > 2 and $lastLoop < 16){
usleep(1000);
}elseif($lastLoop < 128){
usleep(2000);
}else{
usleep(10000);
}
}else{
$lastLoop = 0;
}
}
}
@ -1904,22 +1950,29 @@ class Server{
}
private function checkTickUpdates($currentTick){
//TODO: move this to each Level
//Update entities that need update
if(count(Entity::$needUpdate) > 0){
Timings::$tickEntityTimer->startTiming();
foreach(Entity::$needUpdate as $id => $entity){
if($entity->onUpdate() === false){
unset(Entity::$needUpdate[$id]);
}
}
Timings::$tickEntityTimer->stopTiming();
}
//Update tiles that need update
if(count(Tile::$needUpdate) > 0){
Timings::$tickTileEntityTimer->startTiming();
foreach(Tile::$needUpdate as $id => $tile){
if($tile->onUpdate() === false){
unset(Tile::$needUpdate[$id]);
}
}
Timings::$tickTileEntityTimer->stopTiming();
}
//TODO: Add level blocks
@ -1931,14 +1984,19 @@ class Server{
}
public function doAutoSave(){
/*foreach($this->getOnlinePlayers() as $player){
$player->save();
}*/
Timings::$worldSaveTimer->startTiming();
foreach($this->getOnlinePlayers() as $index => $player){
if($player->isOnline()){
$player->save();
}elseif(!$player->isConnected()){
unset($this->players[$index]);
}
}
foreach($this->getLevels() as $level){
$level->save();
$level->save(false);
}
Timings::$worldSaveTimer->stopTiming();
}
public function doLevelGC(){
@ -1953,20 +2011,21 @@ class Server{
return;
}
}
echo "Sending usage\n";
$plist = "";
foreach($this->getPluginManager()->getPlugins() as $p){
$d = $p->getDescription();
$plist .= str_replace(array(";", ":"), "", $d->getName()) . ":" . str_replace(array(";", ":"), "", $d->getVersion()) . ";";
$plist .= str_replace([";", ":"], "", $d->getName()) . ":" . str_replace([";", ":"], "", $d->getVersion()) . ";";
}
$version = new VersionString();
$this->lastSendUsage = new SendUsageTask("http://stats.pocketmine.net/usage.php", array(
$this->lastSendUsage = new SendUsageTask("http://stats.pocketmine.net/usage.php", [
"serverid" => Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() . ":" . $this->getPort()), 0, 8)),
"port" => $this->getPort(),
"os" => Utils::getOS(),
"memory_total" => $this->getConfigString("memory-limit"),
"memory_usage" => memory_get_usage(),
"php_version" => \pocketmine\PHP_VERSION,
"php_version" => PHP_VERSION,
"version" => $version->get(false),
"build" => $version->getBuild(),
"mc_version" => \pocketmine\MINECRAFT_VERSION,
@ -1974,14 +2033,14 @@ class Server{
"online" => count($this->players),
"max" => $this->getMaxPlayers(),
"plugins" => $plist,
));
]);
$this->scheduler->scheduleAsyncTask($this->lastSendUsage);
}
public function titleTick(){
private function titleTick(){
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0 and \pocketmine\ANSI === true){
echo "\x1b]0;PocketMine-MP " . $this->getPocketMineVersion() . " | Online " . count($this->players) . "/" . $this->getMaxPlayers() . " | RAM " . round((memory_get_usage() / 1024) / 1024, 2) . "/" . round((memory_get_usage(true) / 1024) / 1024, 2) . " MB | U -1 D -1 kB/s | TPS " . $this->getTicksPerSecond() . "\x07";
echo "\x1b]0;". $this->getName() . " " . $this->getPocketMineVersion() . " | Online " . count($this->players) . "/" . $this->getMaxPlayers() . " | RAM " . round((memory_get_usage() / 1024) / 1024, 2) . "/" . round((memory_get_usage(true) / 1024) / 1024, 2) . " MB | U " . round($this->mainInterface->getUploadUsage() / 1024, 2) . " D " . round($this->mainInterface->getDownloadUsage() / 1024, 2) . " kB/s | TPS " . $this->getTicksPerSecond() . "\x07";
}
}
@ -1996,11 +2055,15 @@ class Server{
return false;
}
Timings::$serverTickTimer->startTiming();
$this->inTick = true; //Fix race conditions
++$this->tickCounter;
$this->checkConsole();
Timings::$schedulerTimer->startTiming();
$this->scheduler->mainThreadHeartbeat($this->tickCounter);
Timings::$schedulerTimer->stopTiming();
$this->checkTickUpdates($this->tickCounter);
if(($this->tickCounter & 0b1111) === 0){
@ -2010,11 +2073,15 @@ class Server{
}
}
TimingsHandler::tick();
$this->tickMeasure = (($time = microtime(true)) - $this->tickTime);
$this->tickTime = $time;
$this->nextTick = 0.05 * (0.05 / max(0.05, $this->tickMeasure)) + $time;
$this->inTick = false;
Timings::$serverTickTimer->stopTiming();
return true;
}

34
src/pocketmine/Thread.php Normal file
View File

@ -0,0 +1,34 @@
<?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;
/**
* This class must be extended by all custom threading classes
*/
abstract class Thread extends \Thread{
public final function start($options = PTHREADS_INHERIT_ALL){
ThreadManager::getInstance()->add($this);
return parent::start($options & ~PTHREADS_INHERIT_CLASSES);
}
}

View File

@ -0,0 +1,69 @@
<?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;
class ThreadManager extends \Threaded{
/** @var ThreadManager */
private static $instance = null;
public static function init(){
self::$instance = new ThreadManager();
}
/**
* @return ThreadManager
*/
public static function getInstance(){
return self::$instance;
}
/**
* @param Worker|Thread $thread
*/
public function add($thread){
if($thread instanceof Thread or $thread instanceof Worker){
$this->{spl_object_hash($thread)} = $thread;
}
}
/**
* @param Worker|Thread $thread
*/
public function remove($thread){
if($thread instanceof Thread or $thread instanceof Worker){
unset($this->{spl_object_hash($thread)});
}
}
/**
* @return Worker[]|Thread[]
*/
public function getAll(){
$array = [];
foreach($this as $key => $thread){
$array[$key] = $thread;
}
return $array;
}
}

34
src/pocketmine/Worker.php Normal file
View File

@ -0,0 +1,34 @@
<?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;
/**
* This class must be extended by all custom threading classes
*/
abstract class Worker extends \Worker{
public final function start($options = PTHREADS_INHERIT_ALL){
ThreadManager::getInstance()->add($this);
return parent::start($options & ~PTHREADS_INHERIT_CLASSES);
}
}

View File

@ -29,8 +29,8 @@ class AcaciaWoodStairs extends Stair{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
}

View File

@ -21,30 +21,31 @@
namespace pocketmine\block;
use pocketmine\math\AxisAlignedBB;
/**
* Air block
*/
class Air extends Transparent{
public $isActivable = false;
public $breakable = false;
public $isFlowable = true;
public $isTransparent = true;
public $isReplaceable = true;
public $isPlaceable = false;
public $hasPhysics = false;
public $isSolid = false;
public $isFullBlock = true;
protected $id = self::AIR;
protected $meta = 0;
protected $name = "Air";
protected $hardness = 0;
public function __construct(){
parent::__construct(self::AIR, 0, "Air");
$this->isActivable = false;
$this->breakable = false;
$this->isFlowable = true;
$this->isTransparent = true;
$this->isReplaceable = true;
$this->isPlaceable = false;
$this->hasPhysics = false;
$this->isSolid = false;
$this->isFullBlock = true;
$this->hardness = 0;
}
public function getBoundingBox(){
return new AxisAlignedBB(0, 0, 0, 0, 0, 0);
return null;
}
}

View File

@ -22,6 +22,7 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\network\protocol\ChatPacket;
use pocketmine\Player;
@ -34,13 +35,18 @@ class Bed extends Transparent{
}
public function onActivate(Item $item, Player $player = null){
/*if($player instanceof Player and Server::getInstance()->api->time->getPhase($this->getLevel()) !== "night"){
$time = $this->getLevel()->getTime() % Level::TIME_FULL;
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
if($player instanceof Player and !$isNight){
$pk = new ChatPacket;
$pk->message = "You can only sleep at night";
$player->dataPacket($pk);
return true;
}*/
}
$blockNorth = $this->getSide(2); //Gets the blocks around them
$blockSouth = $this->getSide(3);
@ -57,10 +63,12 @@ class Bed extends Transparent{
$b = $blockEast;
}elseif($blockWest->getID() === $this->id and ($blockWest->meta & 0x08) === 0x08){
$b = $blockWest;
}elseif($player instanceof Player){
$pk = new ChatPacket;
$pk->message = "This bed is incomplete";
$player->dataPacket($pk);
}else{
if($player instanceof Player){
$pk = new ChatPacket;
$pk->message = "This bed is incomplete";
$player->dataPacket($pk);
}
return true;
}
@ -78,12 +86,12 @@ class Bed extends Transparent{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->isTransparent === false){
$faces = array(
$faces = [
0 => 3,
1 => 4,
2 => 2,
3 => 5,
);
];
$d = $player instanceof Player ? $player->getDirection() : 0;
$next = $this->getSide($faces[(($d + 3) % 4)]);
$downNext = $this->getSide(0);
@ -132,9 +140,9 @@ class Bed extends Transparent{
}
public function getDrops(Item $item){
return array(
array(Item::BED, 0, 1),
);
return [
[Item::BED, 0, 1],
];
}
}

View File

@ -32,6 +32,10 @@ class Beetroot extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
@ -82,10 +86,10 @@ class Beetroot extends Flowable{
public function getDrops(Item $item){
$drops = [];
if($this->meta >= 0x07){
$drops[] = array(Item::BEETROOT, 0, 1);
$drops[] = array(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3));
$drops[] = [Item::BEETROOT, 0, 1];
$drops[] = [Item::BEETROOT_SEEDS, 0, mt_rand(0, 3)];
}else{
$drops[] = array(Item::BEETROOT_SEEDS, 0, 1);
$drops[] = [Item::BEETROOT_SEEDS, 0, 1];
}
return $drops;

View File

@ -29,8 +29,8 @@ class BirchWoodStairs extends Stair{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
}

View File

@ -24,6 +24,8 @@
*/
namespace pocketmine\block;
use pocketmine\entity\Villager;
use pocketmine\entity\Zombie;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\level\Position;
@ -97,7 +99,7 @@ abstract class Block extends Position implements Metadatable{
const OBSIDIAN = 49;
const TORCH = 50;
const FIRE = 51;
const MONSTER_SPAWNER = 52;
const WOOD_STAIRS = 53;
const WOODEN_STAIRS = 53;
const OAK_WOOD_STAIRS = 53;
@ -166,12 +168,16 @@ abstract class Block extends Position implements Metadatable{
const FENCE_GATE = 107;
const BRICK_STAIRS = 108;
const STONE_BRICK_STAIRS = 109;
const MYCELIUM = 110;
const NETHER_BRICKS = 112;
const NETHER_BRICK_BLOCK = 112;
const NETHER_BRICKS_STAIRS = 114;
const END_PORTAL = 120;
const END_STONE = 121;
const SANDSTONE_STAIRS = 128;
const EMERALD_ORE = 129;
@ -218,17 +224,19 @@ abstract class Block extends Position implements Metadatable{
const HARDENED_CLAY = 172;
const COAL_BLOCK = 173;
const PODZOL = 243;
const BEETROOT_BLOCK = 244;
const STONECUTTER = 245;
const GLOWING_OBSIDIAN = 246;
const NETHER_REACTOR = 247;
public static $creative = array(
public static $creative = [
//Building
[Item::COBBLESTONE, 0],
[Item::STONE_BRICKS, 0],
[Item::STONE_BRICKS, 1],
[Item::STONE_BRICKS, 2],
[Item::STONE_BRICKS, 3],
[Item::MOSS_STONE, 0],
[Item::WOODEN_PLANKS, 0],
[Item::WOODEN_PLANKS, 1],
@ -246,9 +254,9 @@ abstract class Block extends Position implements Metadatable{
[Item::STONE, 5],
[Item::STONE, 6],
[Item::DIRT, 0],
//TODO: PODZOL
[Item::PODZOL, 0],
[Item::GRASS, 0],
//TODO: MYCELIUM
[Item::MYCELIUM, 0],
[Item::CLAY_BLOCK, 0],
[Item::HARDENED_CLAY, 0],
[Item::STAINED_CLAY, 0],
@ -271,6 +279,7 @@ abstract class Block extends Position implements Metadatable{
[Item::SANDSTONE, 1],
[Item::SANDSTONE, 2],
[Item::SAND, 0],
[Item::SAND, 1],
[Item::GRAVEL, 0],
[Item::TRUNK, 0],
[Item::TRUNK, 1],
@ -318,7 +327,7 @@ abstract class Block extends Position implements Metadatable{
[Item::OBSIDIAN, 0],
[Item::ICE, 0],
[Item::SNOW_BLOCK, 0],
//TODO: ENDSTONE
[Item::END_STONE, 0],
//Decoration
[Item::COBBLESTONE_WALL, 0],
@ -351,6 +360,7 @@ abstract class Block extends Position implements Metadatable{
[Item::CHEST, 0],
[Item::FURNACE, 0],
//TODO: End Portal
[Item::END_PORTAL, 0],
[Item::DANDELION, 0],
[Item::POPPY, 0],
//TODO: blue orchid
@ -396,7 +406,7 @@ abstract class Block extends Position implements Metadatable{
[Item::LEAVES2, 1],
[Item::CAKE, 0],
[Item::SIGN, 0],
//TODO: Monster Spawner
[Item::MONSTER_SPAWNER, 0],
[Item::WOOL, 0],
[Item::WOOL, 7],
[Item::WOOL, 6],
@ -446,11 +456,11 @@ abstract class Block extends Position implements Metadatable{
[Item::CLOCK, 0],
[Item::COMPASS, 0],
[Item::MINECART, 0],
//TODO: Villager
[Item::SPAWN_EGG, 10], //Chicken
[Item::SPAWN_EGG, 11], //Cow
[Item::SPAWN_EGG, 12], //Pig
[Item::SPAWN_EGG, 13], //Sheep
[Item::SPAWN_EGG, Villager::NETWORK_ID],
//[Item::SPAWN_EGG, 10], //Chicken
//[Item::SPAWN_EGG, 11], //Cow
//[Item::SPAWN_EGG, 12], //Pig
//[Item::SPAWN_EGG, 13], //Sheep
//TODO: Wolf
//TODO: Mooshroom
//TODO: Creeper
@ -458,7 +468,7 @@ abstract class Block extends Position implements Metadatable{
//TODO: Silverfish
//TODO: Skeleton
//TODO: Slime
//TODO: Zombie
[Item::SPAWN_EGG, Zombie::NETWORK_ID],
//TODO: PigZombie
//TODO: Replace with Entity constants
@ -490,15 +500,15 @@ abstract class Block extends Position implements Metadatable{
[Item::DYE, 9],
[Item::DYE, 8],
);
];
/** @var Block[] */
public static $list = [];
protected $id;
protected $meta;
protected $name;
protected $breakTime;
protected $hardness;
protected $name = "Unknown";
protected $breakTime = 0.20;
protected $hardness = 10;
public $isActivable = false;
public $breakable = true;
public $isFlowable = false;
@ -516,140 +526,144 @@ abstract class Block extends Position implements Metadatable{
public static function init(){
if(count(self::$list) === 0){
self::$list = array(
self::AIR => new Air(),
self::STONE => new Stone(),
self::GRASS => new Grass(),
self::DIRT => new Dirt(),
self::COBBLESTONE => new Cobblestone(),
self::PLANKS => new Planks(),
self::SAPLING => new Sapling(),
self::BEDROCK => new Bedrock(),
self::WATER => new Water(),
self::STILL_WATER => new StillWater(),
self::LAVA => new Lava(),
self::STILL_LAVA => new StillLava(),
self::SAND => new Sand(),
self::GRAVEL => new Gravel(),
self::GOLD_ORE => new GoldOre(),
self::IRON_ORE => new IronOre(),
self::COAL_ORE => new CoalOre(),
self::WOOD => new Wood(),
self::LEAVES => new Leaves(),
self::SPONGE => new Sponge(),
self::GLASS => new Glass(),
self::LAPIS_ORE => new LapisOre(),
self::LAPIS_BLOCK => new Lapis(),
self::SANDSTONE => new Sandstone(),
self::BED_BLOCK => new Bed(),
self::COBWEB => new Cobweb(),
self::TALL_GRASS => new TallGrass(),
self::DEAD_BUSH => new DeadBush(),
self::WOOL => new Wool(),
self::DANDELION => new Dandelion(),
self::POPPY => new CyanFlower(),
self::BROWN_MUSHROOM => new BrownMushroom(),
self::RED_MUSHROOM => new RedMushroom(),
self::GOLD_BLOCK => new Gold(),
self::IRON_BLOCK => new Iron(),
self::DOUBLE_SLAB => new DoubleSlab(),
self::SLAB => new Slab(),
self::BRICKS_BLOCK => new Bricks(),
self::TNT => new TNT(),
self::BOOKSHELF => new Bookshelf(),
self::MOSS_STONE => new MossStone(),
self::OBSIDIAN => new Obsidian(),
self::TORCH => new Torch(),
self::FIRE => new Fire(),
self::$list = [
self::AIR => Air::class,
self::STONE => Stone::class,
self::GRASS => Grass::class,
self::DIRT => Dirt::class,
self::COBBLESTONE => Cobblestone::class,
self::PLANKS => Planks::class,
self::SAPLING => Sapling::class,
self::BEDROCK => Bedrock::class,
self::WATER => Water::class,
self::STILL_WATER => StillWater::class,
self::LAVA => Lava::class,
self::STILL_LAVA => StillLava::class,
self::SAND => Sand::class,
self::GRAVEL => Gravel::class,
self::GOLD_ORE => GoldOre::class,
self::IRON_ORE => IronOre::class,
self::COAL_ORE => CoalOre::class,
self::WOOD => Wood::class,
self::LEAVES => Leaves::class,
self::SPONGE => Sponge::class,
self::GLASS => Glass::class,
self::LAPIS_ORE => LapisOre::class,
self::LAPIS_BLOCK => Lapis::class,
self::SANDSTONE => Sandstone::class,
self::BED_BLOCK => Bed::class,
self::COBWEB => Cobweb::class,
self::TALL_GRASS => TallGrass::class,
self::DEAD_BUSH => DeadBush::class,
self::WOOL => Wool::class,
self::DANDELION => Dandelion::class,
self::POPPY => CyanFlower::class,
self::BROWN_MUSHROOM => BrownMushroom::class,
self::RED_MUSHROOM => RedMushroom::class,
self::GOLD_BLOCK => Gold::class,
self::IRON_BLOCK => Iron::class,
self::DOUBLE_SLAB => DoubleSlab::class,
self::SLAB => Slab::class,
self::BRICKS_BLOCK => Bricks::class,
self::TNT => TNT::class,
self::BOOKSHELF => Bookshelf::class,
self::MOSS_STONE => MossStone::class,
self::OBSIDIAN => Obsidian::class,
self::TORCH => Torch::class,
self::FIRE => Fire::class,
self::MONSTER_SPAWNER => MonsterSpawner::class,
self::WOOD_STAIRS => WoodStairs::class,
self::CHEST => Chest::class,
self::WOOD_STAIRS => new WoodStairs(),
self::CHEST => new Chest(),
self::DIAMOND_ORE => DiamondOre::class,
self::DIAMOND_BLOCK => Diamond::class,
self::WORKBENCH => Workbench::class,
self::WHEAT_BLOCK => Wheat::class,
self::FARMLAND => Farmland::class,
self::FURNACE => Furnace::class,
self::BURNING_FURNACE => BurningFurnace::class,
self::SIGN_POST => SignPost::class,
self::WOOD_DOOR_BLOCK => WoodDoor::class,
self::LADDER => Ladder::class,
self::DIAMOND_ORE => new DiamondOre(),
self::DIAMOND_BLOCK => new Diamond(),
self::WORKBENCH => new Workbench(),
self::WHEAT_BLOCK => new Wheat(),
self::FARMLAND => new Farmland(),
self::FURNACE => new Furnace(),
self::BURNING_FURNACE => new BurningFurnace(),
self::SIGN_POST => new SignPost(),
self::WOOD_DOOR_BLOCK => new WoodDoor(),
self::LADDER => new Ladder(),
self::COBBLESTONE_STAIRS => CobblestoneStairs::class,
self::WALL_SIGN => WallSign::class,
self::COBBLESTONE_STAIRS => new CobblestoneStairs(),
self::WALL_SIGN => new WallSign(),
self::IRON_DOOR_BLOCK => IronDoor::class,
self::REDSTONE_ORE => RedstoneOre::class,
self::GLOWING_REDSTONE_ORE => GlowingRedstoneOre::class,
self::IRON_DOOR_BLOCK => new IronDoor(),
self::REDSTONE_ORE => new RedstoneOre(),
self::GLOWING_REDSTONE_ORE => new GlowingRedstoneOre(),
self::SNOW_LAYER => SnowLayer::class,
self::ICE => Ice::class,
self::SNOW_BLOCK => Snow::class,
self::CACTUS => Cactus::class,
self::CLAY_BLOCK => Clay::class,
self::SUGARCANE_BLOCK => Sugarcane::class,
self::SNOW_LAYER => new SnowLayer(),
self::ICE => new Ice(),
self::SNOW_BLOCK => new Snow(),
self::CACTUS => new Cactus(),
self::CLAY_BLOCK => new Clay(),
self::SUGARCANE_BLOCK => new Sugarcane(),
self::FENCE => Fence::class,
self::PUMPKIN => Pumpkin::class,
self::NETHERRACK => Netherrack::class,
self::SOUL_SAND => SoulSand::class,
self::GLOWSTONE_BLOCK => Glowstone::class,
self::FENCE => new Fence(),
self::PUMPKIN => new Pumpkin(),
self::NETHERRACK => new Netherrack(),
self::SOUL_SAND => new SoulSand(),
self::GLOWSTONE_BLOCK => new Glowstone(),
self::LIT_PUMPKIN => LitPumpkin::class,
self::CAKE_BLOCK => Cake::class,
self::LIT_PUMPKIN => new LitPumpkin(),
self::CAKE_BLOCK => new Cake(),
self::TRAPDOOR => Trapdoor::class,
self::TRAPDOOR => new Trapdoor(),
self::STONE_BRICKS => StoneBricks::class,
self::STONE_BRICKS => new StoneBricks(),
self::IRON_BARS => IronBars::class,
self::GLASS_PANE => GlassPane::class,
self::MELON_BLOCK => Melon::class,
self::PUMPKIN_STEM => PumpkinStem::class,
self::MELON_STEM => MelonStem::class,
self::IRON_BARS => new IronBars(),
self::GLASS_PANE => new GlassPane(),
self::MELON_BLOCK => new Melon(),
self::PUMPKIN_STEM => new PumpkinStem(),
self::MELON_STEM => new MelonStem(),
self::FENCE_GATE => FenceGate::class,
self::BRICK_STAIRS => BrickStairs::class,
self::STONE_BRICK_STAIRS => StoneBrickStairs::class,
self::FENCE_GATE => new FenceGate(),
self::BRICK_STAIRS => new BrickStairs(),
self::STONE_BRICK_STAIRS => new StoneBrickStairs(),
self::MYCELIUM => Mycelium::class,
self::NETHER_BRICKS => NetherBrick::class,
self::NETHER_BRICKS => new NetherBrick(),
self::NETHER_BRICKS_STAIRS => NetherBrickStairs::class,
self::NETHER_BRICKS_STAIRS => new NetherBrickStairs(),
self::END_PORTAL => EndPortal::class,
self::END_STONE => EndStone::class,
self::SANDSTONE_STAIRS => SandstoneStairs::class,
self::EMERALD_ORE => EmeraldOre::class,
self::SANDSTONE_STAIRS => new SandstoneStairs(),
self::EMERALD_ORE => new EmeraldOre(),
self::EMERALD_BLOCK => Emerald::class,
self::SPRUCE_WOOD_STAIRS => SpruceWoodStairs::class,
self::BIRCH_WOOD_STAIRS => BirchWoodStairs::class,
self::JUNGLE_WOOD_STAIRS => JungleWoodStairs::class,
self::STONE_WALL => StoneWall::class,
self::EMERALD_BLOCK => new Emerald(),
self::SPRUCE_WOOD_STAIRS => new SpruceWoodStairs(),
self::BIRCH_WOOD_STAIRS => new BirchWoodStairs(),
self::JUNGLE_WOOD_STAIRS => new JungleWoodStairs(),
self::STONE_WALL => new StoneWall(),
self::CARROT_BLOCK => Carrot::class,
self::POTATO_BLOCK => Potato::class,
self::CARROT_BLOCK => new Carrot(),
self::POTATO_BLOCK => new Potato(),
self::QUARTZ_BLOCK => Quartz::class,
self::QUARTZ_STAIRS => QuartzStairs::class,
self::DOUBLE_WOOD_SLAB => DoubleWoodSlab::class,
self::WOOD_SLAB => WoodSlab::class,
self::STAINED_CLAY => StainedClay::class,
self::QUARTZ_BLOCK => new Quartz(),
self::QUARTZ_STAIRS => new QuartzStairs(),
self::DOUBLE_WOOD_SLAB => new DoubleWoodSlab(),
self::WOOD_SLAB => new WoodSlab(),
self::STAINED_CLAY => new StainedClay(),
self::LEAVES2 => Leaves2::class,
self::WOOD2 => Wood2::class,
self::ACACIA_WOOD_STAIRS => AcaciaWoodStairs::class,
self::DARK_OAK_WOOD_STAIRS => DarkOakWoodStairs::class,
self::LEAVES2 => new Leaves2(),
self::WOOD2 => new Wood2(),
self::ACACIA_WOOD_STAIRS => new AcaciaWoodStairs(),
self::DARK_OAK_WOOD_STAIRS => new DarkOakWoodStairs(),
self::HAY_BALE => HayBale::class,
self::CARPET => Carpet::class,
self::HARDENED_CLAY => HardenedClay::class,
self::COAL_BLOCK => Coal::class,
self::HAY_BALE => new HayBale(),
self::CARPET => new Carpet(),
self::HARDENED_CLAY => new HardenedClay(),
self::COAL_BLOCK => new Coal(),
self::BEETROOT_BLOCK => new Beetroot(),
self::STONECUTTER => new Stonecutter(),
self::GLOWING_OBSIDIAN => new GlowingObsidian(),
self::NETHER_REACTOR => new NetherReactor(),
);
self::PODZOL => Podzol::class,
self::BEETROOT_BLOCK => Beetroot::class,
self::STONECUTTER => Stonecutter::class,
self::GLOWING_OBSIDIAN => GlowingObsidian::class,
self::NETHER_REACTOR => NetherReactor::class,
];
}
}
@ -662,11 +676,12 @@ abstract class Block extends Position implements Metadatable{
*/
public static function get($id, $meta = 0, Position $pos = null){
if(isset(self::$list[$id])){
$block = clone self::$list[$id];
$block->setDamage($meta);
$block = self::$list[$id];
$block = new $block($meta);
}else{
$block = new Generic($id, $meta);
}
if($pos instanceof Position){
$block->position($pos);
}
@ -683,8 +698,6 @@ abstract class Block extends Position implements Metadatable{
$this->id = (int) $id;
$this->meta = (int) $meta;
$this->name = $name;
$this->breakTime = 0.20;
$this->hardness = 10;
}
/**
@ -726,17 +739,12 @@ abstract class Block extends Position implements Metadatable{
* Sets the block position to a new Position object
*
* @param Position $v
*
* @throws \RuntimeException
*/
final public function position(Position $v){
if(!$v->isValid()){
throw new \RuntimeException("Undefined Level reference");
}
$this->x = (int) $v->x;
$this->y = (int) $v->y;
$this->z = (int) $v->z;
$this->setLevel($v->getLevel(), false);
$this->level = $v->level;
}
/**
@ -751,7 +759,7 @@ abstract class Block extends Position implements Metadatable{
return [];
}else{
return [
array($this->id, $this->meta, 1),
[$this->id, $this->meta, 1],
];
}
}
@ -815,9 +823,9 @@ abstract class Block extends Position implements Metadatable{
* @param AxisAlignedBB $bb
* @param Block[] $list
*/
public function collidesWithBB(AxisAlignedBB $bb, &$list = array()){
public function collidesWithBB(AxisAlignedBB $bb, &$list = []){
$bb2 = $this->getBoundingBox();
if($bb2->intersectsWith($bb)){
if($bb2 !== null and $bb2->intersectsWith($bb)){
$list[] = $bb2;
}
}
@ -894,4 +902,4 @@ abstract class Block extends Position implements Metadatable{
$this->getLevel()->getBlockMetadata()->removeMetadata($this, $metadataKey, $plugin);
}
}
}
}

View File

@ -48,9 +48,9 @@ class Bricks extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::BRICKS_BLOCK, 0, 1),
);
return [
[Item::BRICKS_BLOCK, 0, 1],
];
}else{
return [];
}

View File

@ -54,4 +54,9 @@ class BrownMushroom extends Flowable{
return false;
}
public function getBoundingBox(){
return null;
}
}

View File

@ -39,21 +39,21 @@ class BurningFurnace extends Solid{
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$faces = array(
$faces = [
0 => 4,
1 => 2,
2 => 5,
3 => 3,
);
];
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
$this->getLevel()->setBlock($block, $this, true, false, true);
$nbt = new Compound(false, array(
$nbt = new Compound(false, [
new Enum("Items", []),
new String("id", Tile::FURNACE),
new Int("x", $this->x),
new Int("y", $this->y),
new Int("z", $this->z)
));
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
new Furnace($this->getLevel()->getChunkAt($this->x >> 4, $this->z >> 4), $nbt);
@ -73,13 +73,13 @@ class BurningFurnace extends Solid{
if($t instanceof Furnace){
$furnace = $t;
}else{
$nbt = new Compound(false, array(
$nbt = new Compound(false, [
new Enum("Items", []),
new String("id", Tile::FURNACE),
new Int("x", $this->x),
new Int("y", $this->y),
new Int("z", $this->z)
));
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$furnace = new Furnace($this->getLevel()->getChunkAt($this->x >> 4, $this->z >> 4), $nbt);
}
@ -114,14 +114,14 @@ class BurningFurnace extends Solid{
public function getDrops(Item $item){
$drops = [];
if($item->isPickaxe() >= 1){
$drops[] = array(Item::FURNACE, 0, 1);
$drops[] = [Item::FURNACE, 0, 1];
}
$t = $this->getLevel()->getTile($this);
if($t instanceof Furnace){
for($s = 0; $s < $t->getInventory()->getSize(); ++$s){
$slot = $t->getInventory()->getItem($s);
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$drops[] = array($slot->getID(), $slot->getDamage(), $slot->getCount());
$drops[] = [$slot->getID(), $slot->getDamage(), $slot->getCount()];
}
}
}

View File

@ -25,7 +25,6 @@ use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3 as Vector3;
use pocketmine\Player;
use pocketmine\Server;
class Cactus extends Transparent{
public function __construct($meta = 0){
@ -39,7 +38,7 @@ class Cactus extends Transparent{
$down = $this->getSide(0);
if($down->getID() !== self::SAND and $down->getID() !== self::CACTUS){ //Replace with common break method
$this->getLevel()->setBlock($this, new Air(), false);
Server::getInstance()->api->entity->drop($this, Item::get($this->id));
$this->getLevel()->dropItem($this, Item::get($this->id));
return Level::BLOCK_UPDATE_NORMAL;
}
@ -85,8 +84,8 @@ class Cactus extends Transparent{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
}

View File

@ -28,7 +28,7 @@ use pocketmine\Player;
class Carpet extends Flowable{
public function __construct($meta = 0){
parent::__construct(self::CARPET, $meta, "Carpet");
$names = array(
$names = [
0 => "White Carpet",
1 => "Orange Carpet",
2 => "Magenta Carpet",
@ -45,7 +45,7 @@ class Carpet extends Flowable{
13 => "Green Carpet",
14 => "Red Carpet",
15 => "Black Carpet",
);
];
$this->name = $names[$this->meta];
$this->hardness = 0;
$this->isFullBlock = false;

View File

@ -32,6 +32,11 @@ class Carrot extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
@ -83,9 +88,9 @@ class Carrot extends Flowable{
public function getDrops(Item $item){
$drops = [];
if($this->meta >= 0x07){
$drops[] = array(Item::CARROT, 0, mt_rand(1, 4));
$drops[] = [Item::CARROT, 0, mt_rand(1, 4)];
}else{
$drops[] = array(Item::CARROT, 0, 1);
$drops[] = [Item::CARROT, 0, 1];
}
return $drops;

View File

@ -42,12 +42,12 @@ class Chest extends Transparent{
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$faces = array(
$faces = [
0 => 4,
1 => 2,
2 => 5,
3 => 3,
);
];
$chest = false;
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
@ -69,13 +69,13 @@ class Chest extends Transparent{
}
$this->getLevel()->setBlock($block, $this, true, false, true);
$nbt = new Compound(false, array(
$nbt = new Compound(false, [
new Enum("Items", []),
new String("id", Tile::CHEST),
new Int("x", $this->x),
new Int("y", $this->y),
new Int("z", $this->z)
));
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$tile = new TileChest($this->getLevel()->getChunkAt($this->x >> 4, $this->z >> 4), $nbt);
@ -109,13 +109,13 @@ class Chest extends Transparent{
if($t instanceof TileChest){
$chest = $t;
}else{
$nbt = new Compound(false, array(
$nbt = new Compound(false, [
new Enum("Items", []),
new String("id", Tile::CHEST),
new Int("x", $this->x),
new Int("y", $this->y),
new Int("z", $this->z)
));
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$chest = new TileChest($this->getLevel()->getChunkAt($this->x >> 4, $this->z >> 4), $nbt);
}
@ -131,15 +131,15 @@ class Chest extends Transparent{
}
public function getDrops(Item $item){
$drops = array(
array($this->id, 0, 1),
);
$drops = [
[$this->id, 0, 1],
];
$t = $this->getLevel()->getTile($this);
if($t instanceof TileChest){
for($s = 0; $s < $t->getRealInventory()->getSize(); ++$s){
$slot = $t->getRealInventory()->getItem($s);
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$drops[] = array($slot->getID(), $slot->getDamage(), $slot->getCount());
$drops[] = [$slot->getID(), $slot->getDamage(), $slot->getCount()];
}
}
}

View File

@ -30,8 +30,8 @@ class Clay extends Solid{
}
public function getDrops(Item $item){
return array(
array(Item::CLAY, 0, 4),
);
return [
[Item::CLAY, 0, 4],
];
}
}

View File

@ -48,9 +48,9 @@ class Coal extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::COAL_BLOCK, 0, 1),
);
return [
[Item::COAL_BLOCK, 0, 1],
];
}else{
return [];
}

View File

@ -48,9 +48,9 @@ class CoalOre extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::COAL, 0, 1),
);
return [
[Item::COAL, 0, 1],
];
}else{
return [];
}

View File

@ -48,9 +48,9 @@ class Cobblestone extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::COBBLESTONE, 0, 1),
);
return [
[Item::COBBLESTONE, 0, 1],
];
}else{
return [];
}

View File

@ -31,6 +31,11 @@ class CyanFlower extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === 2 or $down->getID() === 3 or $down->getID() === 60){

View File

@ -31,6 +31,11 @@ class Dandelion extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === 2 or $down->getID() === 3 or $down->getID() === 60){

View File

@ -29,8 +29,8 @@ class DarkOakWoodStairs extends Stair{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
}

View File

@ -30,6 +30,11 @@ class DeadBush extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent === true){ //Replace with common break method

View File

@ -42,9 +42,9 @@ class Diamond extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 4){
return array(
array(Item::DIAMOND_BLOCK, 0, 1),
);
return [
[Item::DIAMOND_BLOCK, 0, 1],
];
}else{
return [];
}

View File

@ -42,9 +42,9 @@ class DiamondOre extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 4){
return array(
array(Item::DIAMOND, 0, 1),
);
return [
[Item::DIAMOND, 0, 1],
];
}else{
return [];
}

View File

@ -25,10 +25,15 @@ use pocketmine\item\Item;
use pocketmine\Player;
class Dirt extends Solid{
public $isActivable = true;
protected $hardness = 2.5;
protected $id = self::DIRT;
protected $meta = 0;
protected $name = "Dirt";
public function __construct(){
parent::__construct(self::DIRT, 0, "Dirt");
$this->isActivable = true;
$this->hardness = 2.5;
}
public function onActivate(Item $item, Player $player = null){

View File

@ -57,12 +57,12 @@ abstract class Door extends Transparent{
return false;
}
$direction = $player instanceof Player ? $player->getDirection() : 0;
$face = array(
$face = [
0 => 3,
1 => 4,
2 => 2,
3 => 5,
);
];
$next = $this->getSide($face[(($direction + 2) % 4)]);
$next2 = $this->getSide($face[$direction]);
$metaUp = 0x08;

View File

@ -26,7 +26,7 @@ use pocketmine\item\Item;
class DoubleSlab extends Solid{
public function __construct($meta = 0){
parent::__construct(self::DOUBLE_SLAB, $meta, "Double Slab");
$names = array(
$names = [
0 => "Stone",
1 => "Sandstone",
2 => "Wooden",
@ -34,7 +34,7 @@ class DoubleSlab extends Solid{
4 => "Brick",
5 => "Stone Brick",
6 => "Quartz",
);
];
$this->name = "Double " . $names[$this->meta & 0x07] . " Slab";
$this->hardness = 30;
}
@ -58,9 +58,9 @@ class DoubleSlab extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::SLAB, $this->meta & 0x07, 2),
);
return [
[Item::SLAB, $this->meta & 0x07, 2],
];
}else{
return [];
}

View File

@ -26,14 +26,14 @@ use pocketmine\item\Item;
class DoubleWoodSlab extends Solid{
public function __construct($meta = 0){
parent::__construct(self::DOUBLE_WOOD_SLAB, $meta, "Double Wooden Slab");
$names = array(
$names = [
0 => "Oak",
1 => "Spruce",
2 => "Birch",
3 => "Jungle",
4 => "Acacia",
5 => "Dark Oak",
);
];
$this->name = "Double " . $names[$this->meta & 0x07] . " Wooden Slab";
$this->hardness = 15;
}
@ -56,9 +56,9 @@ class DoubleWoodSlab extends Solid{
}
public function getDrops(Item $item){
return array(
array(Item::WOOD_SLAB, $this->meta & 0x07, 2),
);
return [
[Item::WOOD_SLAB, $this->meta & 0x07, 2],
];
}
}

View File

@ -42,9 +42,9 @@ class Emerald extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 4){
return array(
array(Item::EMERALD_BLOCK, 0, 1),
);
return [
[Item::EMERALD_BLOCK, 0, 1],
];
}else{
return [];
}

View File

@ -42,9 +42,9 @@ class EmeraldOre extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 4){
return array(
array(Item::EMERALD, 0, 1),
);
return [
[Item::EMERALD, 0, 1],
];
}else{
return [];
}

View File

@ -0,0 +1,29 @@
<?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;
class EndPortal extends Solid{
public function __construct($meta = 0){
parent::__construct(self::END_PORTAL, $meta, "End Portal");
$this->hardness = 18000000;
}
}

View File

@ -0,0 +1,48 @@
<?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 EndStone extends Solid{
public function __construct(){
parent::__construct(self::END_STONE, 0, "End Stone");
$this->hardness = 45;
}
public function getBreakTime(Item $item){
switch($item->isPickaxe()){
case 5:
return 0.6;
case 4:
return 0.75;
case 3:
return 1.15;
case 2:
return 0.4;
case 1:
return 2.25;
default:
return 15;
}
}
}

View File

@ -26,10 +26,7 @@ use pocketmine\Player;
class Fallable extends Solid{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
$this->hasPhysics = true;
}
public $hasPhysics = true;
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$ret = $this->getLevel()->setBlock($this, $this, true, false, true);

View File

@ -30,8 +30,8 @@ class Farmland extends Solid{
}
public function getDrops(Item $item){
return array(
array(Item::DIRT, 0, 1),
);
return [
[Item::DIRT, 0, 1],
];
}
}

View File

@ -37,12 +37,12 @@ class FenceGate extends Transparent{
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$faces = array(
$faces = [
0 => 3,
1 => 0,
2 => 1,
3 => 2,
);
];
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0] & 0x03;
$this->getLevel()->setBlock($block, $this, true, false, true);
@ -50,18 +50,18 @@ class FenceGate extends Transparent{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
public function onActivate(Item $item, Player $player = null){
$faces = array(
$faces = [
0 => 3,
1 => 0,
2 => 1,
3 => 2,
);
];
$this->meta = ($faces[$player instanceof Player ? $player->getDirection() : 0] & 0x03) | ((~$this->meta) & 0x04);
if(($this->meta & 0x04) === 0x04){
$this->isFullBlock = true;

View File

@ -33,6 +33,11 @@ class Fire extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function getDrops(Item $item){
return [];
}

View File

@ -23,10 +23,9 @@ namespace pocketmine\block;
class Flowable extends Transparent{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
$this->isFlowable = true;
$this->isFullBlock = false;
$this->isSolid = false;
}
public $isFlowable = true;
public $isFullBlock = false;
public $isSolid = false;
}

View File

@ -24,19 +24,9 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\Player;
use pocketmine\Server;
class Generic extends Block{
/**
* @param int $id
* @param int $meta
* @param string $name
*/
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
return $this->getLevel()->setBlock($this, $this, true, false, true);
}
@ -53,13 +43,12 @@ class Generic extends Block{
if($this->hasPhysics === true and $type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(0);
if($down->getID() === self::AIR or ($down instanceof Liquid)){
$data = array(
$data = [
"x" => $this->x + 0.5,
"y" => $this->y + 0.5,
"z" => $this->z + 0.5,
"Tile" => $this->id,
);
$server = Server::getInstance();
];
/*$this->getLevel()->setBlock($this, new Air(), false, false, true);
//TODO
//$e = $server->api->entity->add($this->getLevel(), ENTITY_FALLING, FALLING_SAND, $data);

View File

@ -54,9 +54,9 @@ class GlowingRedstoneOre extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 4){
return array(
array(Item::REDSTONE_DUST, 0, mt_rand(4, 5)),
);
return [
[Item::REDSTONE_DUST, 0, mt_rand(4, 5)],
];
}else{
return [];
}

View File

@ -30,8 +30,8 @@ class Glowstone extends Transparent{
}
public function getDrops(Item $item){
return array(
array(Item::GLOWSTONE_DUST, 0, mt_rand(2, 4)),
);
return [
[Item::GLOWSTONE_DUST, 0, mt_rand(2, 4)],
];
}
}

View File

@ -42,9 +42,9 @@ class Gold extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 4){
return array(
array(Item::GOLD_BLOCK, 0, 1),
);
return [
[Item::GOLD_BLOCK, 0, 1],
];
}else{
return [];
}

View File

@ -42,9 +42,9 @@ class GoldOre extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 4){
return array(
array(Item::GOLD_ORE, 0, 1),
);
return [
[Item::GOLD_ORE, 0, 1],
];
}else{
return [];
}

View File

@ -24,15 +24,20 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\generator\object\TallGrass;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\level\Position;
use pocketmine\Player;
use pocketmine\utils\Random;
class Grass extends Solid{
public $isActivable = true;
protected $hardness = 3;
protected $id = self::GRASS;
protected $meta = 0;
protected $name = "Grass";
public function __construct(){
parent::__construct(self::GRASS, 0, "Grass");
$this->isActivable = true;
$this->hardness = 3;
}
public function getDrops(Item $item){
@ -49,7 +54,7 @@ class Grass extends Solid{
$z = mt_rand($this->z - 1, $this->z + 1);
$block = $this->getLevel()->getBlockIdAt($x, $y, $z);
if($block === Block::DIRT){
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
$block = Block::get($block, $this->getLevel()->getBlockDataAt($x, $y, $z), new Position($x, $y, $z, $this->getLevel()));
if($block->getSide(1) instanceof Transparent){
$this->getLevel()->setBlock($block, new Grass());
}

View File

@ -31,14 +31,14 @@ class Gravel extends Fallable{
public function getDrops(Item $item){
if(mt_rand(1, 10) === 1){
return array(
array(Item::FLINT, 0, 1),
);
return [
[Item::FLINT, 0, 1],
];
}
return array(
array(Item::GRAVEL, 0, 1),
);
return [
[Item::GRAVEL, 0, 1],
];
}
}

View File

@ -31,14 +31,14 @@ class HayBale extends Solid{
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$faces = array(
$faces = [
0 => 0,
1 => 0,
2 => 0b1000,
3 => 0b1000,
4 => 0b0100,
5 => 0b0100,
);
];
$this->meta = ($this->meta & 0x03) | $faces[$face];
$this->getLevel()->setBlock($block, $this, true, false, true);
@ -47,9 +47,9 @@ class HayBale extends Solid{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
}

View File

@ -44,9 +44,9 @@ class Iron extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 3){
return array(
array(Item::IRON_BLOCK, 0, 1),
);
return [
[Item::IRON_BLOCK, 0, 1],
];
}else{
return [];
}

View File

@ -49,9 +49,9 @@ class IronDoor extends Door{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::IRON_DOOR, 0, 1),
);
return [
[Item::IRON_DOOR, 0, 1],
];
}else{
return [];
}

View File

@ -44,9 +44,9 @@ class IronOre extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 3){
return array(
array(Item::IRON_ORE, 0, 1),
);
return [
[Item::IRON_ORE, 0, 1],
];
}else{
return [];
}

View File

@ -29,8 +29,8 @@ class JungleWoodStairs extends Stair{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
}

View File

@ -33,14 +33,19 @@ class Ladder extends Transparent{
$this->hardness = 2;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
if($target->isTransparent === false){
$faces = array(
$faces = [
2 => 2,
3 => 3,
4 => 4,
5 => 5,
);
];
if(isset($faces[$face])){
$this->meta = $faces[$face];
$this->getLevel()->setBlock($block, $this, true, false, true);
@ -65,8 +70,8 @@ class Ladder extends Transparent{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
}

View File

@ -44,9 +44,9 @@ class Lapis extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 3){
return array(
array(Item::LAPIS_BLOCK, 0, 1),
);
return [
[Item::LAPIS_BLOCK, 0, 1],
];
}else{
return [];
}

View File

@ -45,9 +45,9 @@ class LapisOre extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 3){
return array(
array(Item::DYE, 4, mt_rand(4, 8)),
);
return [
[Item::DYE, 4, mt_rand(4, 8)],
];
}else{
return [];
}

View File

@ -33,9 +33,14 @@ class Lava extends Liquid{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$ret = $this->getLevel()->setBlock($this, $this, true, false, true);
Server::getInstance()->api->block->scheduleBlockUpdate(clone $this, 40, Level::BLOCK_UPDATE_NORMAL);
$this->getLevel()->scheduleUpdate(clone $this, 40);
return $ret;
}
@ -85,7 +90,7 @@ class Lava extends Liquid{
}
public function onUpdate($type){
//return false;
return false;
$newId = $this->id;
$level = $this->meta & 0x07;
if($type !== Level::BLOCK_UPDATE_NORMAL){

View File

@ -35,12 +35,12 @@ class Leaves extends Transparent{
public function __construct($meta = 0){
parent::__construct(self::LEAVES, $meta, "Leaves");
$names = array(
$names = [
self::OAK => "Oak Leaves",
self::SPRUCE => "Spruce Leaves",
self::BIRCH => "Birch Leaves",
self::JUNGLE => "Jungle Leaves",
);
];
$this->name = $names[$this->meta & 0x03];
$this->hardness = 1;
}
@ -148,13 +148,13 @@ class Leaves extends Transparent{
public function getDrops(Item $item){
$drops = [];
if($item->isShears()){
$drops[] = array(Item::LEAVES, $this->meta & 0x03, 1);
$drops[] = [Item::LEAVES, $this->meta & 0x03, 1];
}else{
if(mt_rand(1, 20) === 1){ //Saplings
$drops[] = array(Item::SAPLING, $this->meta & 0x03, 1);
$drops[] = [Item::SAPLING, $this->meta & 0x03, 1];
}
if(($this->meta & 0x03) === self::OAK and mt_rand(1, 200) === 1){ //Apples
$drops[] = array(Item::APPLE, 0, 1);
$drops[] = [Item::APPLE, 0, 1];
}
}

View File

@ -29,10 +29,10 @@ class Leaves2 extends Leaves{
public function __construct($meta = 0){
Transparent::__construct(self::LEAVES, $meta, "Leaves");
$names = array(
$names = [
self::ACACIA => "Acacia Leaves",
self::DARK_OAK => "Dark Oak Leaves",
);
];
$this->name = $names[$this->meta & 0x03];
$this->hardness = 1;
}
@ -137,10 +137,10 @@ class Leaves2 extends Leaves{
public function getDrops(Item $item){
$drops = [];
if($item->isShears()){
$drops[] = array(Item::LEAVES2, $this->meta & 0x03, 1);
$drops[] = [Item::LEAVES2, $this->meta & 0x03, 1];
}else{
if(mt_rand(1, 20) === 1){ //Saplings
$drops[] = array(Item::SAPLING, $this->meta & 0x03, 1);
$drops[] = [Item::SAPLING, $this->meta & 0x03, 1];
}
}

View File

@ -23,12 +23,9 @@ namespace pocketmine\block;
class Liquid extends Transparent{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
$this->isLiquid = true;
$this->breakable = false;
$this->isReplaceable = true;
$this->isSolid = false;
$this->isFullBlock = true;
}
public $isLiquid = true;
public $breakable = false;
public $isReplaceable = true;
public $isSolid = false;
public $isFullBlock = true;
}

View File

@ -31,13 +31,9 @@ class LitPumpkin extends Solid{
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$faces = array(
0 => 4,
1 => 2,
2 => 5,
3 => 3,
);
$this->meta = $faces[$player->getDirection()];
if($player instanceof Player){
$this->meta = (int) $player->getDirection();
}
$this->getLevel()->setBlock($block, $this, true, false, true);
return true;

View File

@ -30,8 +30,8 @@ class Melon extends Transparent{
}
public function getDrops(Item $item){
return array(
array(Item::MELON_SLICE, 0, mt_rand(3, 7)),
);
return [
[Item::MELON_SLICE, 0, mt_rand(3, 7)],
];
}
}

View File

@ -32,6 +32,11 @@ class MelonStem extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
@ -94,8 +99,8 @@ class MelonStem extends Flowable{
}
public function getDrops(Item $item){
return array(
array(Item::MELON_SEEDS, 0, mt_rand(0, 2)),
);
return [
[Item::MELON_SEEDS, 0, mt_rand(0, 2)],
];
}
}

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 MonsterSpawner extends Solid{
public function __construct(){
parent::__construct(self::MONSTER_SPAWNER, 0, "Monster Spawner");
$this->hardness = 25;
}
public function getBreakTime(Item $item){
switch($item->isPickaxe()){
case 5:
return 0.95;
case 4:
return 1.25;
case 3:
return 1.9;
case 2:
return 0.65;
case 1:
return 3.75;
default:
return 25;
}
}
public function getDrops(Item $item){
return [];
}
}

View File

@ -49,9 +49,9 @@ class MossStone extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::MOSS_STONE, $this->meta, 1),
);
return [
[Item::MOSS_STONE, $this->meta, 1],
];
}else{
return [];
}

View File

@ -0,0 +1,55 @@
<?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\level\Position;
class Mycelium extends Solid{
public function __construct(){
parent::__construct(self::MYCELIUM, 0, "Mycelium");
$this->hardness = 2.5;
}
public function getDrops(Item $item){
return [
[Item::DIRT, 0, 1],
];
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_RANDOM){
//TODO: light levels
$x = mt_rand($this->x - 1, $this->x + 1);
$y = mt_rand($this->y - 2, $this->y + 2);
$z = mt_rand($this->z - 1, $this->z + 1);
$block = $this->getLevel()->getBlockIdAt($x, $y, $z);
if($block === Block::DIRT){
$block = Block::get($block, $this->getLevel()->getBlockDataAt($x, $y, $z), new Position($x, $y, $z, $this->getLevel()));
if($block->getSide(1) instanceof Transparent){
$this->getLevel()->setBlock($block, new Mycelium());
}
}
}
}
}

View File

@ -49,9 +49,9 @@ class NetherBrick extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::NETHER_BRICKS, 0, 1),
);
return [
[Item::NETHER_BRICKS, 0, 1],
];
}else{
return [];
}

View File

@ -49,9 +49,9 @@ class Netherrack extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::NETHERRACK, 0, 1),
);
return [
[Item::NETHERRACK, 0, 1],
];
}else{
return [];
}

View File

@ -40,9 +40,9 @@ class Obsidian extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 5){
return array(
array(Item::OBSIDIAN, 0, 1),
);
return [
[Item::OBSIDIAN, 0, 1],
];
}else{
return [];
}

View File

@ -32,14 +32,14 @@ class Planks extends Solid{
public function __construct($meta = 0){
parent::__construct(self::PLANKS, $meta, "Wood Planks");
$names = array(
$names = [
self::OAK => "Oak Wood Planks",
self::SPRUCE => "Spruce Wood Planks",
self::BIRCH => "Birch Wood Planks",
self::JUNGLE => "Jungle Wood Planks",
self::ACACIA => "Acacia Wood Planks",
self::DARK_OAK => "Jungle Wood Planks",
);
];
$this->name = $names[$this->meta & 0x07];
$this->hardness = 15;
}

View File

@ -19,9 +19,11 @@
*
*/
namespace pocketmine\entity;
class FallingBlock extends Entity{
namespace pocketmine\block;
class Podzol extends Solid{
public function __construct(){
parent::__construct(self::PODZOL, 0, "Podzol");
$this->hardness = 2.5;
}
}

View File

@ -32,6 +32,11 @@ class Potato extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
@ -84,9 +89,9 @@ class Potato extends Flowable{
public function getDrops(Item $item){
$drops = [];
if($this->meta >= 0x07){
$drops[] = array(Item::POTATO, 0, mt_rand(1, 4));
$drops[] = [Item::POTATO, 0, mt_rand(1, 4)];
}else{
$drops[] = array(Item::POTATO, 0, 1);
$drops[] = [Item::POTATO, 0, 1];
}
return $drops;

View File

@ -32,6 +32,11 @@ class PumpkinStem extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
@ -95,8 +100,8 @@ class PumpkinStem extends Flowable{
}
public function getDrops(Item $item){
return array(
array(Item::PUMPKIN_SEEDS, 0, mt_rand(0, 2)),
);
return [
[Item::PUMPKIN_SEEDS, 0, mt_rand(0, 2)],
];
}
}

View File

@ -26,12 +26,12 @@ use pocketmine\item\Item;
class Quartz extends Solid{
public function __construct($meta = 0){
parent::__construct(self::QUARTZ_BLOCK, $meta, "Quartz Block");
$names = array(
$names = [
0 => "Quartz Block",
1 => "Chiseled Quartz Block",
2 => "Quartz Pillar",
3 => "Quartz Pillar",
);
];
$this->name = $names[$this->meta & 0x03];
}
@ -55,9 +55,9 @@ class Quartz extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::QUARTZ_BLOCK, $this->meta & 0x03, 1),
);
return [
[Item::QUARTZ_BLOCK, $this->meta & 0x03, 1],
];
}else{
return [];
}

View File

@ -31,6 +31,11 @@ class RedMushroom extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent === true){ //Replace with common break method

View File

@ -42,9 +42,9 @@ class RedstoneOre extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 2){
return array(
array(Item::REDSTONE_DUST, 0, mt_rand(4, 5)),
);
return [
[Item::REDSTONE_DUST, 0, mt_rand(4, 5)],
];
}else{
return [];
}

View File

@ -26,11 +26,11 @@ use pocketmine\item\Item;
class Sandstone extends Solid{
public function __construct($meta = 0){
parent::__construct(self::SANDSTONE, $meta, "Sandstone");
$names = array(
$names = [
0 => "Sandstone",
1 => "Chiseled Sandstone",
2 => "Smooth Sandstone",
);
];
$this->name = $names[$this->meta & 0x03];
$this->hardness = 4;
}
@ -55,9 +55,9 @@ class Sandstone extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::SANDSTONE, $this->meta & 0x03, 1),
);
return [
[Item::SANDSTONE, $this->meta & 0x03, 1],
];
}else{
return [];
}

View File

@ -37,18 +37,23 @@ class Sapling extends Flowable{
public function __construct($meta = Sapling::OAK){
parent::__construct(self::SAPLING, $meta, "Sapling");
$this->isActivable = true;
$names = array(
$names = [
0 => "Oak Sapling",
1 => "Spruce Sapling",
2 => "Birch Sapling",
3 => "Jungle Sapling",
4 => "Acacia Sapling",
5 => "Dark Oak Sapling",
);
];
$this->name = $names[$this->meta & 0x07];
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::GRASS or $down->getID() === self::DIRT or $down->getID() === self::FARMLAND){
@ -102,8 +107,8 @@ class Sapling extends Flowable{
}
public function getDrops(Item $item){
return array(
array($this->id, $this->meta & 0x07, 1),
);
return [
[$this->id, $this->meta & 0x07, 1],
];
}
}

View File

@ -33,14 +33,19 @@ class SignPost extends Transparent{
$this->hardness = 5;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
if($face !== 0){
$faces = array(
$faces = [
2 => 2,
3 => 3,
4 => 4,
5 => 5,
);
];
if(!isset($faces[$face])){
$this->meta = floor((($player->yaw + 180) * 16 / 360) + 0.5) & 0x0F;
$this->getLevel()->setBlock($block, Block::get(Item::SIGN_POST, $this->meta), true, false, true);
@ -78,8 +83,8 @@ class SignPost extends Transparent{
}
public function getDrops(Item $item){
return array(
array(Item::SIGN, 0, 1),
);
return [
[Item::SIGN, 0, 1],
];
}
}

View File

@ -27,7 +27,7 @@ use pocketmine\Player;
class Slab extends Transparent{
public function __construct($meta = 0){
parent::__construct(self::SLAB, $meta, "Slab");
$names = array(
$names = [
0 => "Stone",
1 => "Sandstone",
2 => "Wooden",
@ -36,7 +36,7 @@ class Slab extends Transparent{
5 => "Stone Brick",
6 => "Quartz",
7 => "",
);
];
$this->name = (($this->meta & 0x08) === 0x08 ? "Upper " : "") . $names[$this->meta & 0x07] . " Slab";
if(($this->meta & 0x08) === 0x08){
$this->isFullBlock = true;
@ -116,9 +116,9 @@ class Slab extends Transparent{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array($this->id, $this->meta & 0x07, 1),
);
return [
[$this->id, $this->meta & 0x07, 1],
];
}else{
return [];
}

View File

@ -34,6 +34,11 @@ class SnowLayer extends Flowable{
$this->hardness = 0.5;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down instanceof Solid){
@ -59,9 +64,9 @@ class SnowLayer extends Flowable{
public function getDrops(Item $item){
if($item->isShovel() !== false){
return array(
array(Item::SNOWBALL, 0, 1),
);
return [
[Item::SNOWBALL, 0, 1],
];
}
return [];

View File

@ -29,8 +29,8 @@ class SpruceWoodStairs extends Stair{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
}

View File

@ -26,7 +26,7 @@ use pocketmine\item\Item;
class StainedClay extends Solid{
public function __construct($meta = 0){
parent::__construct(self::STAINED_CLAY, $meta, "Stained Clay");
$names = array(
$names = [
0 => "White Stained Clay",
1 => "Orange Stained Clay",
2 => "Magenta Stained Clay",
@ -43,7 +43,7 @@ class StainedClay extends Solid{
13 => "Green Stained Clay",
14 => "Red Stained Clay",
15 => "Black Stained Clay",
);
];
$this->name = $names[$this->meta];
$this->hardness = 30;
}

View File

@ -37,12 +37,12 @@ class Stair extends Transparent{
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$faces = array(
$faces = [
0 => 0,
1 => 2,
2 => 1,
3 => 3,
);
];
$this->meta = $faces[$player->getDirection()] & 0x03;
if(($fy > 0.5 and $face !== 1) or $face === 0){
$this->meta |= 0x04; //Upside-down stairs
@ -54,9 +54,9 @@ class Stair extends Transparent{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}else{
return [];
}

View File

@ -24,7 +24,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Stone extends Solid{
const STONE = 0;
const NORMAL = 0;
const GRANITE = 1;
const POLISHED_GRANITE = 2;
const DIORITE = 3;
@ -32,10 +32,13 @@ class Stone extends Solid{
const ANDESITE = 5;
const POLISHED_ANDESITE = 6;
protected $hardness = 30;
protected $id = self::STONE;
public function __construct($meta = 0){
parent::__construct(self::STONE, $meta, "Stone");
$this->meta = $meta;
$names = [
self::STONE => "Stone",
self::NORMAL => "Stone",
self::GRANITE => "Granite",
self::POLISHED_GRANITE => "Polished Granite",
self::DIORITE => "Diorite",
@ -44,11 +47,9 @@ class Stone extends Solid{
self::POLISHED_ANDESITE => "Polished Andesite",
];
$this->name = $names[$this->meta & 0x07];
$this->hardness = 30;
}
public function getBreakTime(Item $item){
switch($item->isPickaxe()){
case 5:
return 0.4;
@ -67,9 +68,9 @@ class Stone extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::COBBLESTONE, 0, 1),
);
return [
[Item::COBBLESTONE, 0, 1],
];
}else{
return [];
}

View File

@ -26,12 +26,12 @@ use pocketmine\item\Item;
class StoneBricks extends Solid{
public function __construct($meta = 0){
parent::__construct(self::STONE_BRICKS, $meta, "Stone Bricks");
$names = array(
$names = [
0 => "Stone Bricks",
1 => "Mossy Stone Bricks",
2 => "Cracked Stone Bricks",
3 => "Chiseled Stone Bricks",
);
];
$this->name = $names[$this->meta & 0x03];
$this->hardness = 30;
}
@ -56,9 +56,9 @@ class StoneBricks extends Solid{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array(Item::STONE_BRICKS, $this->meta & 0x03, 1),
);
return [
[Item::STONE_BRICKS, $this->meta & 0x03, 1],
];
}else{
return [];
}

View File

@ -40,8 +40,8 @@ class Stonecutter extends Solid{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
}

View File

@ -32,10 +32,15 @@ class Sugarcane extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function getDrops(Item $item){
return array(
array(Item::SUGARCANE, 0, 1),
);
return [
[Item::SUGARCANE, 0, 1],
];
}
public function onActivate(Item $item, Player $player = null){

View File

@ -36,13 +36,13 @@ class TNT extends Solid{
if(($player->gamemode & 0x01) === 0){
$item->useOn($this);
}
$data = array(
$data = [
"x" => $this->x + 0.5,
"y" => $this->y + 0.5,
"z" => $this->z + 0.5,
"power" => 4,
"fuse" => 20 * 4, //4 seconds
);
];
$this->getLevel()->setBlock($this, new Air(), false, false, true);
//TODO
//$e = Server::getInstance()->api->entity->add($this->level, ENTITY_OBJECT, OBJECT_PRIMEDTNT, $data);

View File

@ -28,15 +28,20 @@ class TallGrass extends Flowable{
public function __construct($meta = 1){
parent::__construct(self::TALL_GRASS, $meta, "Tall Grass");
$this->isReplaceable = true;
$names = array(
$names = [
0 => "Dead Shrub",
1 => "Tall Grass",
2 => "Fern",
);
];
$this->name = $names[$this->meta & 0x03];
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent === true){ //Replace with common break method
@ -50,28 +55,11 @@ class TallGrass extends Flowable{
}
public function getDrops(Item $item){
$drops = [];
$possibleDrops = array(
array(Item::WHEAT_SEEDS, 0, 1),
array(Item::CARROT, 0, 1),
array(Item::POTATO, 0, 1),
array(Item::BEETROOT_SEEDS, 0, 1),
array(Item::MELON_SEEDS, 0, 1),
array(Item::PUMPKIN_SEEDS, 0, 1),
0,
0,
0,
0,
0,
0,
0,
0,
);
if(($item = $possibleDrops[mt_rand(0, count($possibleDrops) - 1)]) !== 0){
$drops[] = $item;
if(mt_rand(0, 15) === 0){
return [Item::WHEAT_SEEDS, 0, 1];
}
return $drops;
return [];
}
}

View File

@ -31,10 +31,15 @@ class Torch extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$side = $this->getDamage();
$faces = array(
$faces = [
1 => 4,
2 => 5,
3 => 2,
@ -42,7 +47,7 @@ class Torch extends Flowable{
5 => 0,
6 => 0,
0 => 0,
);
];
if($this->getSide($faces[$side])->isTransparent === true and !($side === 0 and $this->getSide(0)->getID() === self::FENCE)){ //Replace with common break method
//TODO
@ -58,13 +63,13 @@ class Torch extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
if($target->isTransparent === false and $face !== 0){
$faces = array(
$faces = [
1 => 5,
2 => 4,
3 => 3,
4 => 2,
5 => 1,
);
];
$this->meta = $faces[$face];
$this->getLevel()->setBlock($block, $this, true, false, true);
@ -80,8 +85,8 @@ class Torch extends Flowable{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
}

View File

@ -22,16 +22,13 @@
namespace pocketmine\block;
class Transparent extends Generic{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
$this->isActivable = false;
$this->breakable = true;
$this->isFlowable = false;
$this->isTransparent = true;
$this->isReplaceable = false;
$this->isPlaceable = true;
$this->isSolid = true;
}
class Transparent extends Generic{
public $isActivable = false;
public $breakable = true;
public $isFlowable = false;
public $isTransparent = true;
public $isReplaceable = false;
public $isPlaceable = true;
public $isSolid = true;
}

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