Compare commits

..

292 Commits

Author SHA1 Message Date
3de14d8ba6 Preparing release 2015-01-02 01:37:33 +01:00
5fffabe05b Fixed players not calculating onGround correctly 2015-01-02 01:22:33 +01:00
3128ae9736 Improved exception handling and trace creation 2015-01-01 22:50:45 +01:00
7be4e2fa81 Merge pull request #2438 from PocketMine/new-version-format
New release version format
2014-12-31 17:53:12 +01:00
95b305ce87 Detect really big corrupted chunks, closes #2471 2014-12-31 12:40:11 +01:00
767800662c Added chunk check on Level 2014-12-30 15:54:12 +01:00
fe32e6f5d0 Merge branch 'master' into new-version-format 2014-12-29 12:43:15 +01:00
2cec0d9f36 Improved Simplex 2D noise 2014-12-28 03:51:08 +01:00
d800a21bd4 Higher chunk defaults 2014-12-28 02:58:17 +01:00
8d9fbec4ce Fixed memory leak issues on chunk generation under 32-bit hosts, fixed issue with generated chunks not having a provider. Closes #2419, fixes #2308, closes #2421 2014-12-28 02:22:13 +01:00
ab72c32769 Improved Normal generator speed 2014-12-28 02:12:48 +01:00
346626305c Corrected fence crafting recipes, closes #2457 2014-12-28 01:49:42 +01:00
fafbd500e1 Added typehints to HelpCommand 2014-12-28 01:49:10 +01:00
2db2e8cfc4 Block IP addresses on ban-ip 2014-12-26 13:56:35 +01:00
854479180f Move Query exceptions to debug level > 1 2014-12-26 13:47:15 +01:00
902ba81e02 Added automatic/manual RakLib IP address, block addresses when exceptions are thrown 2014-12-26 13:33:41 +01:00
1ac17abec0 Fixed #2446 2014-12-24 23:00:11 +01:00
714ea54121 Players won't take damage 60 ticks after spawning / respawning. 2014-12-24 20:44:22 +01:00
aa992684ba Possible workaround for some PHP bug 2014-12-24 00:55:23 +01:00
0c58de86b7 New version format 2014-12-23 14:02:35 +01:00
7ecac019a9 Bitmask block state 2014-12-23 13:58:30 +01:00
6cb88afe1a Improved block breaking time and event handling 2014-12-22 23:49:17 +01:00
a677bcb331 Increased transaction timeout, not needed anymore due to packet ordering 2014-12-22 23:38:47 +01:00
2f6007342c Fixed server.log created in two different places on path changed 2014-12-22 23:00:28 +01:00
b6c0eb8c96 Added optional parameter for multiple NBT read 2014-12-22 16:25:12 +01:00
afa8496767 Fixed possible memory leak when hiding players from each other 2014-12-21 20:03:39 +01:00
d7be2ce439 Added Chest recreation on imported levels 2014-12-21 14:29:18 +01:00
6dcb5da069 Added Double Plant block, fixes damage walking inside it. 2014-12-21 14:28:45 +01:00
3cf1692c96 Possible fix for #2424 2014-12-21 13:59:04 +01:00
d04af590d1 Updated RakLib
* Fixes issues with packets without messageIndex
* Workarounds possible CPU-hog DoS attack over ACK/NACK packets
2014-12-21 13:45:28 +01:00
d4c43215b1 Fixed typo about async chunk generation 2014-12-19 16:10:01 +01:00
a40918aabf LevelDB load/write fixes 2014-12-19 10:35:16 +01:00
20f9352714 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-12-19 01:07:13 +01:00
a605e90dfc Added experimental LevelDB support, fixed a few issues with NBT, spawning and Binary R/W 2014-12-19 00:28:50 +01:00
9fc250956f Merge pull request #2395 from PEMapModder/patch-6
Allow $base in knockback() to be dynamic and getters/setters in EntityDa...
2014-12-18 20:39:48 +09:00
db2dfc47a6 Update RakLib 2014-12-18 03:33:33 +01:00
408a537001 Added TesterPlugin submodule, updated RakLib to fix packet loop issues 2014-12-17 23:29:57 +01:00
922bfb33ac Updated .gitignore 2014-12-16 18:50:57 +01:00
8e47c93fbc Fixed some issues with chunks being generated on a loop 2014-12-16 02:57:44 +01:00
c175485cd8 Added World Generation timings 2014-12-15 17:52:07 +01:00
b6981cc31d Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-12-15 01:05:55 +01:00
1f9cd6a99b Added default parameter to Config getters, implements and closes #2398 2014-12-15 01:05:32 +01:00
ded7ada7d7 Merge pull request #2399 from PEMapModder/patch-7
Update documentation of PluginBase::getCommand() for IDEs' auto completion
2014-12-15 00:52:43 +01:00
1b50879823 Snow layer recipe added: Fix for #2400 2014-12-13 17:10:17 +01:00
1bd9cbd4d3 Update documentation of PluginBase::getCommand() for IDEs' auto completion 2014-12-13 20:42:23 +08:00
96122d3be7 Allow $base in knockback() to be dynamic and getters/setters in EntityDamageByEntityEvent
This change is backwards-compatible.
2014-12-12 23:01:31 +08:00
71d602a4cf Faster chunk setting on provider 2014-12-12 15:51:31 +01:00
c81bbdaaa9 Possible fix for #2394 2014-12-12 12:05:36 +01:00
2752393c42 Fixed #2392 2014-12-12 12:05:15 +01:00
312e064b07 Updated RakLib, changed some Entity move AABB calls 2014-12-11 17:39:59 +01:00
94f91967f3 Updated RakLib: Implemented packet reordering, fixed packet recovery in both sides, errors are now debug level 2014-12-11 03:13:44 +01:00
fe900b417e Less calls! 2014-12-10 02:42:02 +01:00
4c30b6b8a1 Optimized Liquid spreading, optimized light updates, improved side block get/update, fixed raw set not cleaning Block cache (TNT explosions) 2014-12-10 00:37:04 +01:00
c41ac7b0a2 Updated PocketMine-SPL, added trait autoloading 2014-12-09 16:33:42 +01:00
b220bd2a45 Updated chunk indexes on generator 2014-12-09 15:14:11 +01:00
04ee94dc91 Fixed #2388 2014-12-09 15:05:36 +01:00
ea8f10efa4 Limited death animation to Living entities 2014-12-09 14:57:28 +01:00
04ecbd1a76 Level optimization, added new chunk/block hashes 2014-12-09 14:55:21 +01:00
ddfc9d9ce1 Fixed players not getting sound when they are harmed 2014-12-09 02:22:42 +01:00
a4735eaf76 Replaced some instanceof to null checks 2014-12-09 02:22:18 +01:00
306f492fc0 Added Player death animations, improved spawning behavior to correct invisible players, fixed players getting stuck when dead, closes #2304 2014-12-09 01:36:46 +01:00
5e5f8bf33d Better block creation on Level 2014-12-08 22:02:36 +01:00
3bb2f12cde Improved block reading
* Created global block states array
* Improved Level->getBlock() using block states
* Improved Level->getBlock() for 64-bit systems
* Added Level->getFullBlock()
* Added FullChunk->getFullBlock()
* Added Chunk->getFullBlock()
* Added ChunkSection->getFullBlock()
* Deprecated FullChunk->getBlock()
* Deprecated Chunk->getBlock()
* Deprecated ChunkSection->getBlock()
2014-12-08 20:54:47 +01:00
1041bb0e6a Do not quiet error messages when parsing config files 2014-12-07 23:21:47 +01:00
49e93cee80 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-12-07 22:05:58 +01:00
8b6681c56d FIxed some preprocessor includes 2014-12-07 22:05:45 +01:00
9e3d432b9e Faster Level provider chunk unloading 2014-12-07 21:51:57 +01:00
841a3d5ee6 Merge pull request #2381 from PocketMine/revert-2379-master
Revert "Fixed small possible error in permission"
2014-12-07 20:54:46 +01:00
a5294d5ec7 Revert "Fixed small possible error in permission" 2014-12-07 20:54:38 +01:00
5373e6be07 Merge pull request #2379 from sudoku173/master
Fixed small possible error in permission
2014-12-07 20:41:08 +01:00
075137bd3c Fixed small possible error in permission
Changed permission to "pocketmine.command.deop" from "pocketmine.command.op.take"
2014-12-07 11:38:44 -08:00
68da4b5b39 Collect unallocated chunks from the Level provider 2014-12-07 18:27:11 +01:00
e4557a2e8e Added HeightMap get/set methods on chunks, Level 2014-12-07 18:02:07 +01:00
964bf98ca6 Added Config->getNested(key) and Config->setNested(key, value) 2014-12-07 16:41:43 +01:00
747f7685e7 Fix formatting issues due to bad IDE settings 2014-12-07 16:30:04 +01:00
bb82e7be50 Handle a hotbar queue to allow using more than the first slot (won't save order due to the protocol) 2014-12-07 16:01:45 +01:00
7506f01302 Improved Item property handling 2014-12-07 15:51:00 +01:00
a98da3bab1 Renamed old getID() calls to getId() 2014-12-07 15:21:32 +01:00
f0d6128282 Use squared distance on movement handling 2014-12-07 15:18:14 +01:00
161e7ae7ec Fix CPU issue when starting without STDIN 2014-12-07 02:42:38 +01:00
6104c5b5a3 API 1.9.0, backwards-compatible 2014-12-07 02:24:45 +01:00
af82d616c1 Block creating and property handling rewrite, part2 2014-12-07 02:20:26 +01:00
a0d4bff385 Block creating and property handling rewrite, part1 2014-12-07 01:53:27 +01:00
79236c971c Possibly fix issues related to new lines on different operating systems and event listeners modifiers 2014-12-05 22:43:31 +01:00
20e63ae543 Force player setting their new position 2014-12-05 02:24:34 +01:00
add7879720 Implemented no damage ticks 2014-12-05 02:24:08 +01:00
1a064d38b1 Merge remote-tracking branch 'origin/master' 2014-12-04 00:04:18 +01:00
294e680d5d Added armor items and max stack size for them. 2014-12-04 00:04:09 +01:00
811970e58d Merge pull request #2352 from PEMapModder/patch-3
Added internal use warning for TaskHandler::cancel()
2014-12-01 12:07:30 +01:00
941961f5ef Added internal use warning for TaskHandler::cancel()
It is confusing for some developers to whether to use this function or `ServerScheduler::cancelTask($taskId)`. It is better to add warning in the documentation.
2014-12-01 16:25:37 +08:00
1963d8fde0 Change last X/Y/Z/Yaw/Pitch on teleport 2014-11-30 12:49:35 +01:00
e44ed4da3b Enabled batch block sending again 2014-11-29 12:58:31 +01:00
a72488d41e Updated player movement processing and event handling 2014-11-29 12:43:34 +01:00
3930f379cf Updated light filter values 2014-11-29 11:58:50 +01:00
66ba327e62 Improved light spread algorithm even more 2014-11-29 11:27:22 +01:00
329ca62465 Improved light spread algorithm 2014-11-28 19:54:25 +01:00
26e47ef694 Removed old revert flag from Player->processMovement() 2014-11-28 14:49:06 +01:00
61ea149ff0 API 1.8.0 2014-11-28 14:44:56 +01:00
b3c3f896a3 Implemented light population, added Level->getFullLight() 2014-11-28 14:44:27 +01:00
d139e5f342 Removed temporal pthreads workaround 2014-11-28 13:01:25 +01:00
3abf36ad07 Fixed invalid worlds property being set by users 2014-11-28 12:47:28 +01:00
0bc9a9bdab Fixed armor dropping twice 2014-11-27 23:19:46 +01:00
98340522d9 Fixed items getting added on the same empty slot 2014-11-27 20:49:18 +01:00
6d09754ea7 Improved Inventory->addItem(), fixed breaking containers duplicating the last slot, removed not necessary slot changes 2014-11-27 20:10:55 +01:00
a3b1d318cc Fixed ladder crafting recipe 2014-11-27 20:02:38 +01:00
f866efb622 Removed unused Block->isLiquid property 2014-11-27 17:26:43 +01:00
b1c4578726 Fixed #2340 2014-11-27 16:18:43 +01:00
f4181a6e36 Bump Minecraft: PE version 2014-11-27 14:37:44 +01:00
38089af098 Improved global entity motion encoding using per-player queues 2014-11-27 14:26:36 +01:00
cd135b39ad Improved player spawn item in hand sending 2014-11-27 13:59:32 +01:00
dd3207cbd8 Possible fix for #2267, #2314 2014-11-27 13:47:17 +01:00
a7abd5ff9d Catch exceptions when chunks are unloaded 2014-11-27 13:35:54 +01:00
a3e50f6337 Properly close inventory windows from Players 2014-11-27 13:32:07 +01:00
441a98e60a Removed old trigger_error() calls, closes #2335 2014-11-27 13:16:39 +01:00
4a90ac270f Improved exception handling and debugging 2014-11-22 13:52:36 +01:00
a906a2988b Bumped Minecraft: PE version string 2014-11-22 13:44:34 +01:00
545f68382c Increased Fence, Fence Gate and Stone Wall Y bounding box 2014-11-22 13:44:05 +01:00
8249cac592 Catch corrupted chunk data errors 2014-11-20 22:02:00 +01:00
7b7bbe9105 Regenerate corrupt player data if invalid data is found 2014-11-20 21:58:27 +01:00
05679c7872 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-11-20 21:46:14 +01:00
8eb80be691 Remove duplicated tiles from chunk table automatically 2014-11-20 21:45:52 +01:00
f55b0d0b45 Merge pull request #2295 from LukeDarling/patch-1
Fixed Server->getOps() capitalization
2014-11-19 13:10:03 +01:00
754e0dbb49 Protect permission removal against bad plugins 2014-11-18 18:43:30 +01:00
525c8db779 Improved chunk loading/unloading 2014-11-18 18:33:24 +01:00
c7f578f297 Possible fix for #2297 2014-11-18 13:57:03 +01:00
19c030281f Fixed #1969 2014-11-18 13:53:38 +01:00
ca9fe1b89a Improved and fixed command exception message, closes #2301 2014-11-18 13:46:00 +01:00
9fd6a695f6 Fixed permission-related memory leak 2014-11-18 13:42:24 +01:00
c07b0ff35b Fixed tile entities not being placed in the correct array 2014-11-15 11:49:09 +01:00
00be3f0dd3 Fixed Server->getOps() capitalization
I'm not 100% sure, but I believe this is how it's supposed to be.
2014-11-15 00:01:57 -05:00
6796fca2b6 Merge pull request #2294 from LukeDarling/patch-1
fixed version message color
2014-11-15 14:20:14 +10:30
5657cce3db fixed version message color 2014-11-14 15:52:38 -05:00
05ac256cc3 Fixed Acacia / Dark Oak logs crafting recipes 2014-11-14 15:58:31 +01:00
49977c5410 Bumped weakref version, fixes travis builds 2014-11-14 10:30:06 +01:00
ca40bb678c Merge pull request #2288 from sekjun9878/master
Get timezone directly. Fixes #2287.
2014-11-13 23:08:22 +10:30
2068cc9cdf Merge pull request #2243 from PEMapModder/patch-1
cmd files comment syntax should be like this.
2014-11-13 21:42:25 +10:30
ea4617cedd Get timezone directly. Fixes #2287. 2014-11-13 21:13:12 +10:30
1a5544f68c Fixed Chunk tile indexes 2014-11-08 15:00:18 +01:00
0128a7aeb2 API version 1.7.1 (fixes) 2014-11-07 09:45:30 +01:00
fd954ce708 Fixed PlayerInventory->setItem() with null items 2014-11-07 09:43:36 +01:00
d63a82de0a MCPE protocol 20 2014-11-06 19:08:32 +01:00
92143d523c Added SetDifficultyPacket 2014-11-06 19:07:24 +01:00
1818e64c8e Merge branch 'master' into 0.10 2014-11-06 18:56:47 +01:00
7e1095e28d Reenabled collision against entities on move 2014-11-06 12:57:17 +01:00
f1519e6d13 Improved Level->getTile() to a direct lookup instead of linear search 2014-11-06 12:34:33 +01:00
3b9a9bcd5d Use proper indexes on Living->getLineOfSight() when a max length is set 2014-11-06 12:23:45 +01:00
263bff01c8 Change RuntimeException to InvalidStateException on BlockIterator 2014-11-06 12:16:12 +01:00
987d647b76 Return proper BlockIterator index, throw more exceptions, improved blockQueue performance 2014-11-06 12:12:31 +01:00
522b75645c Merge branch 'master' into 0.10 2014-11-05 19:04:36 +01:00
9eed0a579c Fixed red sand smelting recipe 2014-11-05 17:41:12 +01:00
064976d32b Fixed ladder recipe 2014-11-05 17:38:23 +01:00
2abb577178 Fixed String -> Wool recipe 2014-11-05 17:36:44 +01:00
127855c220 Fixed Snow block recipe 2014-11-05 17:36:06 +01:00
93c7a3c170 Fixed bonemeal recipe, closes #2260 2014-11-05 17:32:28 +01:00
31903a764a Fixed unloaded chunks residing on memory and getting loaded again causing crash, fixed spawn chunks getting unloaded by players 2014-11-04 17:16:02 +01:00
79bc1d6c85 Fixed server not stopping after a special crash 2014-11-04 17:15:20 +01:00
cc7f12739d Added vertical and horizontal collision detection to Entities 2014-11-04 12:23:42 +01:00
32dae93ef9 Removed unused imports 2014-11-04 12:08:24 +01:00
8fd6582e74 Automatically set Entity / Tile entity save identifiers 2014-11-04 12:04:08 +01:00
a5369b3570 Fixed unloading chunks 2014-11-04 11:18:34 +01:00
abbd33210a Possible fix for #2245 2014-11-04 00:19:50 +01:00
6b6222c09c Allow passing a Player source as last parameter on Inventory->addItem() and Inventory->removeItem() 2014-11-04 00:16:25 +01:00
a8c997d88a ¬¬ 2014-11-03 12:54:46 +01:00
6993718a83 Added EntityDamageByChildEntityEvent 2014-11-03 12:03:37 +01:00
86afecec89 Improved inventory sending, send single slots instead of full inventory as much as possible 2014-11-03 11:48:10 +01:00
29d1fd1fc8 Fixed player viewer list including themselves 2014-11-03 11:29:01 +01:00
af4eb2ab1e Create server.log properly on non-existent directories 2014-11-02 16:15:15 +01:00
f7baf46a54 Fire PlayerInteractEvent on 0xff face 2014-11-02 16:12:51 +01:00
75c0d8324c Fixed some inventory events not firing on players 2014-11-02 13:26:58 +01:00
da4334f06b Revert Armor then Inventory instead of Inventory then Armor on failed transaction 2014-11-01 23:02:59 +01:00
413bd3c0df Use SplFixedArray for improved performance 2014-11-01 22:12:35 +01:00
1a0428654b Updated timings command, give direct link to results 2014-11-01 21:20:44 +01:00
2803a38fd1 Fixed random block updates not firing 2014-11-01 20:26:13 +01:00
95a5ca7889 Added command message to /time add 2014-11-01 20:12:55 +01:00
240f14c425 Fixed #2253 2014-11-01 19:40:15 +01:00
cb9b6ab1d1 Fixed server not using the correct provided path if it did not exist 2014-11-01 19:23:10 +01:00
8a87280566 Added /time start and /time stop 2014-11-01 17:45:11 +01:00
4d97827d44 Improved level switching for players 2014-11-01 17:39:09 +01:00
f8f1e0e9df Despawn entities correctly from clients as they move 2014-11-01 16:47:40 +01:00
bf596ebf05 Fixed Query-related crash 2014-11-01 16:20:40 +01:00
90777014b6 Fixed Stone crash 2014-11-01 16:17:47 +01:00
4a78ffd2dd Fixed FallingSand crash 2014-11-01 16:15:09 +01:00
7c361a52d2 Fixed #2252 2014-11-01 13:52:20 +01:00
13fc0df92c Fixed #2251 2014-11-01 12:40:45 +01:00
d5012f6fcf Fixed server not stopping after a fatal error 2014-11-01 03:07:47 +01:00
4569a73f3d Fixed Entity being set position after being closed 2014-10-31 23:10:29 +01:00
66acb5cdd7 Possible fix for crashing server not stopping 2014-10-31 23:10:12 +01:00
8601405a88 Fixed CPU leak 2014-10-31 21:07:00 +01:00
ae06681b60 Added packet exception handling, updated RakLib 2014-10-31 19:14:59 +01:00
01ffb14e39 Fixed #2204 2014-10-31 17:34:45 +01:00
ce989876af Improved freeing chunks 2014-10-31 16:39:32 +01:00
f8d6ebabf3 Removed some calls 2014-10-31 15:57:07 +01:00
094b600a0c Updated NBT/DataPacket reading 2014-10-31 01:02:31 +01:00
82cfe6ea9c Updated NBT/DataPacket reading 2014-10-31 00:32:50 +01:00
4fba6d7c86 Merge branch 'master' into 0.10 2014-10-30 23:20:59 +01:00
f72d7284b9 Added EncapsulatedPacket reuse on broadcast 2014-10-30 23:20:28 +01:00
8f0527832f Removed extra AxisAlignedBB generation on Door and Trapdoor 2014-10-30 22:15:19 +01:00
f66944368d Update RakLib 2014-10-30 22:06:23 +01:00
7ab3c57b00 Optimized networking code & AxisAlignedBB 2014-10-30 22:06:07 +01:00
673b867ee8 Fixed players not loading chunks when stuck on a unloaded chunk 2014-10-30 20:05:40 +01:00
2424c8a76c Update RakLib, possible fix for notifyACK 2014-10-30 19:44:05 +01:00
92eb5cb0b8 Added LE Triad methods 2014-10-30 17:56:58 +01:00
fd46c71120 Updated RakLib 2014-10-30 17:18:43 +01:00
6a4259bf24 Updated RakLib 2014-10-30 17:04:19 +01:00
9a65279c6a Added ifndef for packets Binary 2014-10-30 16:41:11 +01:00
09a01be709 Added ifndef for NBT Binary 2014-10-30 16:32:57 +01:00
57d1847c50 Updated to receive new optimizations 2014-10-30 16:02:48 +01:00
6e8e2a79dd Fixed Event name being null 2014-10-30 14:52:11 +01:00
d8f9def7f4 Added preprocessor optimizations 2014-10-30 07:58:53 +01:00
8cb9dd9a14 Fixed #2244 2014-10-29 22:58:40 +01:00
c4c374e3fa Added extra chunk sending timings 2014-10-29 21:52:27 +01:00
d57e37896d Improved Region / RakLib 2014-10-29 17:43:21 +01:00
022a978ffb Added InventoryPickupArrowEvent 2014-10-29 16:29:00 +01:00
00b282d40c Improved cache pool cleanup times 2014-10-29 16:13:47 +01:00
8a768cea33 EntityDamageEvent and children now only fire if the attack is possible, moved event trigger to Entity->attack() 2014-10-29 16:02:40 +01:00
289bc56b4b Blocks now save their bounding box, fixed entity block collision check 2014-10-29 15:43:23 +01:00
6f64af3066 Reuse even more objects! 2014-10-29 14:23:51 +01:00
72c09045d5 Fixed Zombie drops crash 2014-10-29 13:21:54 +01:00
5e55c3a8f0 Fixed Chest->unpair() 2014-10-29 13:21:14 +01:00
afaa2cf722 Fixed Double Chest behavior 2014-10-29 12:57:26 +01:00
50cfeaa393 Fixed Stonecutter recipe 2014-10-29 12:36:34 +01:00
dda8b03349 Fixed Bowl recipe 2014-10-29 12:12:54 +01:00
56e848488a Fixed Trapdoor recipe 2014-10-29 12:10:48 +01:00
7e4f862634 Fixed typo in OfflinePlayer 2014-10-29 11:42:29 +01:00
577a7a1c3d cmd files comment syntax should be like this. 2014-10-29 17:20:36 +08:00
78f8d0280d Removed unused imports 2014-10-29 01:14:09 +01:00
0680b98380 Remove chunks from advanced cache after setting 2014-10-29 01:07:30 +01:00
cbe0fe5e46 Added Entity->onGround setting when entities keep moving without checks 2014-10-29 00:41:13 +01:00
7eed92e8fb Use Player->forceMovement on MovePlayerPacket non-tick revert 2014-10-29 00:31:17 +01:00
f772391866 Fixed InventoryPickupItemEvent 2014-10-28 22:05:54 +01:00
8c4faa8622 Added extra Exceptions 2014-10-28 21:07:12 +01:00
b6f7ee20fc Added Error -> Exception handling 2014-10-28 20:43:36 +01:00
0fce83c671 Fixed #2189 2014-10-28 13:27:30 +01:00
8080643cc9 Fixed plugins crashing the server when teleporting players on an invalid event 2014-10-28 13:18:40 +01:00
5bf2174cad Fixed UseItemPacket being able to be sent before spawning 2014-10-28 13:16:20 +01:00
34ae760def New way to spawn entities/tiles using a global register table, allow overriding default entity/tile classes via classes 2014-10-28 13:09:27 +01:00
a5b85c549a Added Snowballs 2014-10-28 12:13:31 +01:00
b9f1812f61 Disallow further modification of Signs by its creator after load/unload 2014-10-28 11:05:32 +01:00
350cee3d41 Added Event allocation pool, updated SPL with Class::onClassLoaded() 2014-10-28 10:47:40 +01:00
144a871c07 Improved Vector3 and Block handling, less allocation on Positions 2014-10-28 10:03:10 +01:00
69492474e4 Improve #2238, do not crash when an invalid/corrupt RCON stop event happens 2014-10-28 02:09:36 +01:00
4299ebebcc Bump API version to 1.6.1 2014-10-28 00:55:07 +01:00
119b429ab8 RakLib update 2014-10-28 00:43:47 +01:00
8f1eb41ca5 RakLib update 2014-10-28 00:23:55 +01:00
ca92d2a0d3 Bumped API version to 1.7.0 2014-10-27 20:30:58 +01:00
db82f76c11 Improved network packets allocation 2014-10-27 20:30:33 +01:00
3f5b129cf5 Updated RakLib 2014-10-27 19:39:24 +01:00
f6aac8728b Mark chunk to be saved when removing invalid entities/tiles 2014-10-27 18:43:58 +01:00
809fc44813 Bump API version to 1.6.1 2014-10-27 16:07:00 +01:00
64f1ff066d Fixed /setworldspawn changing sender data 2014-10-27 15:57:26 +01:00
a5a3f4801a Fixed entities not getting ticks on movement 2014-10-27 15:53:14 +01:00
23d1532ff9 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-10-27 15:44:44 +01:00
ecbbcc2e8e Drop invalid entities / tile entities on chunk loading 2014-10-27 15:44:36 +01:00
7abf52e615 Implemented Vector3 List and AxisAlignedBB Pool to decrease object allocation 2014-10-27 15:39:20 +01:00
9e01e2ef49 Merge pull request #2235 from nno88551/patch-2
Update BaseInventory.php
2014-10-26 15:52:08 +01:00
df81b365e5 Update BaseInventory.php 2014-10-26 22:21:21 +09:00
db8ac0b9cb Merge pull request #2225 from PEMapModder/falling-sand
Update FallingBlock to new Anvil formats, possible fix for #2189
2014-10-25 17:58:47 +02:00
ee4f416d93 Fix FallingBlock.php 2014-10-25 18:15:47 +08:00
8feea721e3 Merge pull request #2223 from Falkirks/set-armour-fix
Fix various get and set armour in PlayerInventory
2014-10-25 12:13:28 +02:00
8e7077ff4b Update FallingBlock to new Anvil formats, possible fix for #2189
I don't have time to test yet, so I am not sure if it does fix it.
2014-10-25 12:26:57 +08:00
4f4a6e7446 Fixes get and set armour 2014-10-24 17:11:59 -07:00
1fc066fc37 Updated time steps from x2.5 to x1.25 2014-10-24 12:12:01 +02:00
b565844062 Merge branch 'master' into 0.10 2014-10-24 12:07:35 +02:00
be948f99cc Fixed #2207 Server crashing if players are closed before logging in 2014-10-24 12:06:55 +02:00
5cb428e5cc Updated build number 2014-10-23 17:23:59 +02:00
d2f4a14d66 Merge branch 'master' into 0.10 2014-10-23 17:21:24 +02:00
516bb37a50 Removed some direct type checks on Entity/Tile->closed 2014-10-21 19:28:29 +02:00
580ade9092 Possible fix for entities not closing correctly 2014-10-21 19:26:16 +02:00
8f7dfe0b71 Removed extra ; from if, fixes #2205 2014-10-21 18:37:29 +02:00
5310ba3ae6 Fixed crash when doing var_dump() of anything that contains the Server object 2014-10-20 13:06:53 +02:00
ef97efcd96 Added explosion death message 2014-10-20 13:00:03 +02:00
30c3718ea8 Improved Explosion item drop position 2014-10-20 12:58:05 +02:00
5437567e95 Merge branch 'master' into 0.10 2014-10-20 12:53:14 +02:00
e3e97a4205 Improved Player->onGround checking 2014-10-20 12:52:00 +02:00
fec387d2ec Fixed entities not being pushed out of blocks 2014-10-20 12:37:17 +02:00
481e2b08ee Removed debug call 2014-10-20 12:05:40 +02:00
15de0eece7 Improved inventory and window allocation, fixes #2200 2014-10-20 09:48:11 +02:00
2f8267aa1e Improved Level object deallocation 2014-10-19 20:45:03 +02:00
f2b573c32f Fixed Level->getMetadata() and similar, removed extra references 2014-10-19 19:51:36 +02:00
34946faf94 Remove errors from Utils::getRandomBytes() 2014-10-19 13:44:38 +02:00
3b47513439 Return result directly on Server->getOfflinePlayer() 2014-10-19 02:49:58 +02:00
7d9a98ec6b Updated UseItemPacket 2014-10-18 23:42:41 +02:00
92facc94b9 Added new fences and fence gates to fuel types 2014-10-18 18:02:39 +02:00
d3327f450c Added different Fence Gates, new Fence Gate crafting recipes 2014-10-18 17:56:18 +02:00
570cab9c66 Added different Fences, new Fence crafting recipes 2014-10-18 17:44:24 +02:00
582ba100b0 Bumped protocol version to 19 2014-10-18 17:01:36 +02:00
4c0daa462d Merge branch 'master' into 0.10 2014-10-18 16:54:03 +02:00
2e6366868d Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-10-18 16:53:42 +02:00
245e9b4f18 Fixes inventory changes getting the wrong window, closes #2187 2014-10-18 16:53:06 +02:00
68e73d4e3a Merge pull request #2188 from aodzip/patch-1
Update Skeleton.php
2014-10-18 15:36:02 +02:00
684617d370 Update Skeleton.php
fixed a little wrong
2014-10-18 21:13:35 +08:00
a879104a6f Minecraft: PE version bump 2014-10-17 14:43:10 +02:00
452 changed files with 8012 additions and 3267 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@ players/*
worlds/*
plugins/*
bin/*
timings/*
*.log
*.txt
*.phar

3
.gitmodules vendored
View File

@ -9,3 +9,6 @@
[submodule "src/spl"]
path = src/spl
url = https://github.com/PocketMine/PocketMine-SPL.git
[submodule "tests/TesterPlugin"]
path = tests/TesterPlugin
url = https://github.com/PocketMine/TesterPlugin.git

View File

@ -10,7 +10,7 @@ before_script:
- mkdir plugins
- wget -O plugins/DevTools.phar https://github.com/PocketMine/DevTools/releases/download/v1.9.0/DevTools_v1.9.0.phar
- pecl install channel://pecl.php.net/pthreads-2.0.10
- pecl install channel://pecl.php.net/weakref-0.2.4
- pecl install channel://pecl.php.net/weakref-0.2.6
- echo | pecl install channel://pecl.php.net/yaml-1.1.1
script:
@ -18,4 +18,4 @@ script:
notifications:
email: false
#webhooks: http://n.tkte.ch/h/214/wsNvmG43-ncxUVRrFPwSM-r0
#webhooks: http://n.tkte.ch/h/214/wsNvmG43-ncxUVRrFPwSM-r0

View File

@ -137,7 +137,7 @@ class CrashDump{
$error = $lastExceptionError;
}else{
$error = (array) error_get_last();
$error["trace"] = getTrace(4);
$error["trace"] = @getTrace(4);
$errorConversion = [
E_ERROR => "E_ERROR",
E_WARNING => "E_WARNING",

File diff suppressed because it is too large Load Diff

View File

@ -65,16 +65,15 @@ namespace {
}
namespace pocketmine {
use LogLevel;
use pocketmine\utils\Binary;
use pocketmine\utils\MainLogger;
use pocketmine\utils\Utils;
use pocketmine\wizard\Installer;
const VERSION = "Alpha_1.4dev";
const API_VERSION = "1.6.0";
const VERSION = "1.4";
const API_VERSION = "1.10.0";
const CODENAME = "絶好(Zekkou)ケーキ(Cake)";
const MINECRAFT_VERSION = "v0.9.5 alpha";
const MINECRAFT_VERSION = "v0.10.4 alpha";
/*
* Startup code. Do not look at it, it may harm you.
@ -122,11 +121,14 @@ namespace pocketmine {
$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);
define("pocketmine\\DATA", isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR);
define("pocketmine\\PLUGIN_PATH", isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
define("pocketmine\\ANSI", (Utils::getOS() !== "win" or isset($opts["enable-ansi"])) and !isset($opts["disable-ansi"]));
@mkdir(\pocketmine\DATA, 0777, true);
//Logger has a dependency on timezone, so we'll set it to UTC until we can get the actual timezone.
date_default_timezone_set("UTC");
$logger = new MainLogger(\pocketmine\DATA . "server.log", \pocketmine\ANSI);
@ -134,15 +136,15 @@ namespace pocketmine {
if(!ini_get("date.timezone")){
if(($timezone = detect_system_timezone()) and date_default_timezone_set($timezone)){
//Success! Timezone has already been set and validated in the if statement.
//This here is just for redundancy just in case some stupid program wants to read timezone data from the ini.
//This here is just for redundancy just in case some program wants to read timezone data from the ini.
ini_set("date.timezone", $timezone);
}else{
//If system timezone detection fails or timezone is an invalid value.
if($response = Utils::getURL("http://ip-api.com/json")
and $ip_geolocation_data = json_decode($response, true)
and $ip_geolocation_data['status'] != 'fail'
and date_default_timezone_set($ip_geolocation_data['timezone']))
{
and date_default_timezone_set($ip_geolocation_data['timezone'])
){
//Again, for redundancy.
ini_set("date.timezone", $ip_geolocation_data['timezone']);
}else{
@ -153,7 +155,8 @@ namespace pocketmine {
}
}else{
/*
* This is here so that stupid idiots don't come to us complaining and fill up the issue tracker when they put an incorrect timezone abbreviation in php.ini apparently.
* This is here so that people don't come to us complaining and fill up the issue tracker when they put
* an incorrect timezone abbreviation in php.ini apparently.
*/
$default_timezone = date_default_timezone_get();
if(strpos($default_timezone, "/") === false){
@ -166,17 +169,30 @@ namespace pocketmine {
function detect_system_timezone(){
switch(Utils::getOS()){
case 'win':
$regex = '/(?:Time Zone:\s*\()(UTC)(\+*\-*\d*\d*\:*\d*\d*)(?:\))/';
$regex = '/(UTC)(\+*\-*\d*\d*\:*\d*\d*)/';
exec("systeminfo", $output);
/*
* wmic timezone get Caption
* Get the timezone offset
*
* Sample Output var_dump
* array(3) {
* [0] =>
* string(7) "Caption"
* [1] =>
* string(20) "(UTC+09:30) Adelaide"
* [2] =>
* string(0) ""
* }
*/
exec("wmic timezone get Caption", $output);
$string = trim(implode("\n", $output));
//Detect the Time Zone string in systeminfo
//Detect the Time Zone string
preg_match($regex, $string, $matches);
if(!isset($matches[2]))
{
if(!isset($matches[2])){
return false;
}
@ -234,6 +250,7 @@ namespace pocketmine {
/**
* @param string $offset In the format of +09:00, +02:00, -04:00 etc.
*
* @return string
*/
function parse_offset($offset){
@ -327,55 +344,7 @@ namespace pocketmine {
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, $context, $trace = null){
global $lastError;
if(error_reporting() === 0){ //@ error-con..trol
return false;
}
$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",
];
$type = ($errno === E_ERROR or $errno === E_USER_ERROR) ? LogLevel::ERROR : (($errno === E_USER_WARNING or $errno === E_WARNING) ? LogLevel::WARNING : LogLevel::NOTICE);
$errno = isset($errorConversion[$errno]) ? $errorConversion[$errno] : $errno;
if(($pos = strpos($errstr, "\n")) !== false){
$errstr = substr($errstr, 0, $pos);
}
$logger = MainLogger::getLogger();
$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;
}
set_error_handler("\\pocketmine\\error_handler", E_ALL);
set_error_handler([\ExceptionHandler::class, "handler"], -1);
$errors = 0;
@ -398,8 +367,8 @@ namespace pocketmine {
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
if(version_compare($pthreads_version, "2.0.8") < 0){
$logger->critical("pthreads >= 2.0.8 is required, while you have $pthreads_version.");
if(version_compare($pthreads_version, "2.0.9") < 0){
$logger->critical("pthreads >= 2.0.9 is required, while you have $pthreads_version.");
++$errors;
}

View File

@ -31,6 +31,15 @@ use pocketmine\command\CommandSender;
use pocketmine\command\ConsoleCommandSender;
use pocketmine\command\PluginIdentifiableCommand;
use pocketmine\command\SimpleCommandMap;
use pocketmine\entity\Arrow;
use pocketmine\entity\Entity;
use pocketmine\entity\FallingSand;
use pocketmine\entity\Human;
use pocketmine\entity\Item as DroppedItem;
use pocketmine\entity\PrimedTNT;
use pocketmine\entity\Snowball;
use pocketmine\entity\Villager;
use pocketmine\entity\Zombie;
use pocketmine\event\HandlerList;
use pocketmine\event\level\LevelInitEvent;
use pocketmine\event\level\LevelLoadEvent;
@ -42,6 +51,7 @@ use pocketmine\inventory\InventoryType;
use pocketmine\inventory\Recipe;
use pocketmine\item\Item;
use pocketmine\level\format\anvil\Anvil;
use pocketmine\level\format\leveldb\LevelDB;
use pocketmine\level\format\LevelProviderManager;
use pocketmine\level\format\mcregion\McRegion;
use pocketmine\level\generator\Flat;
@ -78,11 +88,17 @@ use pocketmine\plugin\PluginManager;
use pocketmine\scheduler\CallbackTask;
use pocketmine\scheduler\SendUsageTask;
use pocketmine\scheduler\ServerScheduler;
use pocketmine\tile\Chest;
use pocketmine\tile\Furnace;
use pocketmine\tile\Sign;
use pocketmine\tile\Tile;
use pocketmine\updater\AutoUpdater;
use pocketmine\utils\Binary;
use pocketmine\utils\Cache;
use pocketmine\utils\Config;
use pocketmine\utils\LevelException;
use pocketmine\utils\MainLogger;
use pocketmine\utils\ServerException;
use pocketmine\utils\TextFormat;
use pocketmine\utils\TextWrapper;
use pocketmine\utils\Utils;
@ -113,6 +129,8 @@ class Server{
/** @var bool */
private $isRunning = true;
private $hasStopped = false;
/** @var PluginManager */
private $pluginManager = null;
@ -132,8 +150,8 @@ class Server{
*/
private $tickCounter;
private $nextTick = 0;
private $tickAverage = [20,20,20,20,20];
private $useAverage = [20,20,20,20,20];
private $tickAverage = [20, 20, 20, 20, 20];
private $useAverage = [20, 20, 20, 20, 20];
/** @var \AttachableThreadedLogger */
private $logger;
@ -282,7 +300,7 @@ class Server{
* @return int
*/
public function getViewDistance(){
return max(56, $this->getProperty("chunk-sending.max-chunks"));
return max(56, $this->getProperty("chunk-sending.max-chunks", 256));
}
/**
@ -296,7 +314,7 @@ class Server{
* @return string
*/
public function getServerName(){
return $this->getConfigString("motd", "Unknown server");
return $this->getConfigString("motd", "Minecraft: PE Server");
}
/**
@ -604,15 +622,36 @@ class Server{
$this->mainInterface->putRaw($address, $port, $payload);
}
/**
* Blocks an IP address from the main interface. Setting timeout to -1 will block it forever
*
* @param string $address
* @param int $timeout
*/
public function blockAddress($address, $timeout = 300){
$this->mainInterface->blockAddress($address, $timeout);
}
/**
* @param string $address
* @param int $port
* @param string $payload
*/
public function handlePacket($address, $port, $payload){
if(strlen($payload) > 2 and substr($payload, 0, 2) === "\xfe\xfd" and $this->queryHandler instanceof QueryHandler){
$this->queryHandler->handle($address, $port, $payload);
} //TODO: add raw packet events
try{
if(strlen($payload) > 2 and substr($payload, 0, 2) === "\xfe\xfd" and $this->queryHandler instanceof QueryHandler){
$this->queryHandler->handle($address, $port, $payload);
}
}catch(\Exception $e){
if(\pocketmine\DEBUG > 1){
if($this->logger instanceof MainLogger){
$this->logger->logException($e);
}
}
$this->blockAddress($address, 600);
}
//TODO: add raw packet events
}
/**
@ -643,7 +682,7 @@ class Server{
$result = $this->getPlayerExact($name);
if($result === null){
$result = new OfflinePlayer($this, $name);
return new OfflinePlayer($this, $name);
}
return $result;
@ -657,107 +696,112 @@ class Server{
public function getOfflinePlayerData($name){
$name = strtolower($name);
$path = $this->getDataPath() . "players/";
if(!file_exists($path . "$name.dat")){
$spawn = $this->getDefaultLevel()->getSafeSpawn();
$nbt = new Compound(false, [
new Long("firstPlayed", floor(microtime(true) * 1000)),
new Long("lastPlayed", floor(microtime(true) * 1000)),
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 Enum("Inventory", []),
new Compound("Achievements", []),
new Int("playerGameType", $this->getGamemode()),
new Enum("Motion", [
new Double(0, 0.0),
new Double(1, 0.0),
new Double(2, 0.0)
]),
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);
$nbt->Rotation->setTagType(NBT::TAG_Float);
if(file_exists($path . "$name.dat")){
try{
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->readCompressed(file_get_contents($path . "$name.dat"));
if(file_exists($path . "$name.yml")){ //Importing old PocketMine-MP files
$data = new Config($path . "$name.yml", Config::YAML, []);
$nbt["playerGameType"] = (int) $data->get("gamemode");
$nbt["Level"] = $data->get("position")["level"];
$nbt["Pos"][0] = $data->get("position")["x"];
$nbt["Pos"][1] = $data->get("position")["y"];
$nbt["Pos"][2] = $data->get("position")["z"];
$nbt["SpawnLevel"] = $data->get("spawn")["level"];
$nbt["SpawnX"] = (int) $data->get("spawn")["x"];
$nbt["SpawnY"] = (int) $data->get("spawn")["y"];
$nbt["SpawnZ"] = (int) $data->get("spawn")["z"];
$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, [
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, [
new Short("id", $item["id"]),
new Short("Damage", $item["Damage"]),
new Byte("Count", $item["Count"]),
new Byte("Slot", $slot),
new Byte("TrueSlot", $item["TrueSlot"])
]);
}
}
foreach($data->get("armor") as $slot => $item){
if(count($item) === 2){
$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){
$nbt->Achievements[$achievement] = new Byte($achievement, $status == true ? 1 : 0);
}
unlink($path . "$name.yml");
}else{
$this->logger->notice("Player data not found for \"" . $name . "\", creating new profile");
return $nbt->getData();
}catch(\Exception $e){ //zlib decode error / corrupt data
rename($path . "$name.dat", $path . "$name.dat.bak");
$this->logger->warning("Corrupted data found for \"" . $name . "\", creating new profile");
}
$this->saveOfflinePlayerData($name, $nbt);
return $nbt;
}else{
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt->readCompressed(file_get_contents($path . "$name.dat"));
return $nbt->getData();
$this->logger->notice("Player data not found for \"" . $name . "\", creating new profile");
}
$spawn = $this->getDefaultLevel()->getSafeSpawn();
$nbt = new Compound(false, [
new Long("firstPlayed", floor(microtime(true) * 1000)),
new Long("lastPlayed", floor(microtime(true) * 1000)),
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 Enum("Inventory", []),
new Compound("Achievements", []),
new Int("playerGameType", $this->getGamemode()),
new Enum("Motion", [
new Double(0, 0.0),
new Double(1, 0.0),
new Double(2, 0.0)
]),
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);
$nbt->Rotation->setTagType(NBT::TAG_Float);
if(file_exists($path . "$name.yml")){ //Importing old PocketMine-MP files
$data = new Config($path . "$name.yml", Config::YAML, []);
$nbt["playerGameType"] = (int) $data->get("gamemode");
$nbt["Level"] = $data->get("position")["level"];
$nbt["Pos"][0] = $data->get("position")["x"];
$nbt["Pos"][1] = $data->get("position")["y"];
$nbt["Pos"][2] = $data->get("position")["z"];
$nbt["SpawnLevel"] = $data->get("spawn")["level"];
$nbt["SpawnX"] = (int) $data->get("spawn")["x"];
$nbt["SpawnY"] = (int) $data->get("spawn")["y"];
$nbt["SpawnZ"] = (int) $data->get("spawn")["z"];
$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, [
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, [
new Short("id", $item["id"]),
new Short("Damage", $item["Damage"]),
new Byte("Count", $item["Count"]),
new Byte("Slot", $slot),
new Byte("TrueSlot", $item["TrueSlot"])
]);
}
}
foreach($data->get("armor") as $slot => $item){
if(count($item) === 2){
$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){
$nbt->Achievements[$achievement] = new Byte($achievement, $status == true ? 1 : 0);
}
unlink($path . "$name.yml");
}
$this->saveOfflinePlayerData($name, $nbt);
return $nbt;
}
/**
@ -915,7 +959,7 @@ class Server{
*/
public function unloadLevel(Level $level, $forceUnload = false){
if($level->unload($forceUnload) === true){
unset($this->levels[$level->getID()]);
unset($this->levels[$level->getId()]);
return true;
}
@ -930,11 +974,11 @@ class Server{
*
* @return bool
*
* @throws \Exception
* @throws LevelException
*/
public function loadLevel($name){
if(trim($name) === ""){
throw new \Exception("Invalid empty level name");
throw new LevelException("Invalid empty level name");
}
if($this->isLevelLoaded($name)){
return true;
@ -962,11 +1006,13 @@ class Server{
$level = new Level($this, $name, $path, $provider);
}catch(\Exception $e){
$this->logger->error("Could not load level \"" . $name . "\": " . $e->getMessage());
if($this->logger instanceof MainLogger){
$this->logger->logException($e);
}
return false;
}
$this->levels[$level->getID()] = $level;
$this->levels[$level->getId()] = $level;
$level->initLevel();
@ -1083,7 +1129,7 @@ class Server{
return false;
}
$seed = $seed === null ? Binary::readInt(Utils::getRandomBytes(4, false)) : (int) $seed;
$seed = $seed === null ? Binary::readInt(@Utils::getRandomBytes(4, false)) : (int) $seed;
if($generator !== null and class_exists($generator) and is_subclass_of($generator, Generator::class)){
$generator = new $generator($options);
@ -1101,7 +1147,7 @@ class Server{
$provider::generate($path, $name, $seed, $generator, $options);
$level = new Level($this, $name, $path, $provider);
$this->levels[$level->getID()] = $level;
$this->levels[$level->getId()] = $level;
$level->initLevel();
@ -1195,24 +1241,9 @@ class Server{
* @return mixed
*/
public function getProperty($variable, $defaultValue = null){
$vars = explode(".", $variable);
$base = array_shift($vars);
if($this->config->exists($base)){
$base = $this->config->get($base);
}else{
return $defaultValue;
}
$value = $this->config->getNested($variable);
while(count($vars) > 0){
$baseKey = array_shift($vars);
if(is_array($base) and isset($base[$baseKey])){
$base = $base[$baseKey];
}else{
return $defaultValue;
}
}
return $base;
return $value === null ? $defaultValue : $value;
}
/**
@ -1377,7 +1408,7 @@ class Server{
/**
* @return Config
*/
public function getOPs(){
public function getOps(){
return $this->operators;
}
@ -1415,7 +1446,7 @@ class Server{
}
/**
* @param \ClassLoader $autoloader
* @param \ClassLoader $autoloader
* @param \ThreadedLogger $logger
* @param string $filePath
* @param string $dataPath
@ -1427,11 +1458,12 @@ class Server{
$this->autoloader = $autoloader;
$this->logger = $logger;
$this->filePath = $filePath;
$this->dataPath = $dataPath;
$this->pluginPath = $pluginPath;
@mkdir($this->dataPath . "worlds/", 0777, true);
@mkdir($this->dataPath . "players/", 0777);
@mkdir($this->pluginPath, 0777);
@mkdir($dataPath . "worlds/", 0777);
@mkdir($dataPath . "players/", 0777);
@mkdir($pluginPath, 0777);
$this->dataPath = realpath($dataPath) . DIRECTORY_SEPARATOR;
$this->pluginPath = realpath($pluginPath) . DIRECTORY_SEPARATOR;
$this->entityMetadata = new EntityMetadataStore();
$this->playerMetadata = new PlayerMetadataStore();
@ -1488,7 +1520,7 @@ class Server{
"level-type" => "DEFAULT",
"enable-query" => true,
"enable-rcon" => false,
"rcon.password" => substr(base64_encode(Utils::getRandomBytes(20, false)), 3, 10),
"rcon.password" => substr(base64_encode(@Utils::getRandomBytes(20, false)), 3, 10),
"auto-save" => true,
]);
@ -1534,13 +1566,13 @@ class Server{
}
$this->logger->info("Starting Minecraft PE server on " . ($this->getIp() === "" ? "*" : $this->getIp()) . ":" . $this->getPort());
define("BOOTUP_RANDOM", Utils::getRandomBytes(16));
define("BOOTUP_RANDOM", @Utils::getRandomBytes(16));
$this->serverID = Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() . $this->getPort()), 0, 8));
$this->addInterface($this->mainInterface = new RakLibInterface($this));
$this->logger->info("This server is running " . $this->getName() . " version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(true) . 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->logger->info("This server is running " . $this->getName() . " version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(true) . TextFormat::WHITE . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")");
$this->logger->info($this->getName() . " is distributed under the LGPL License");
PluginManager::$pluginParentTimer = new TimingsHandler("** Plugins");
Timings::init();
@ -1548,6 +1580,9 @@ class Server{
$this->consoleSender = new ConsoleCommandSender();
$this->commandMap = new SimpleCommandMap($this);
$this->registerEntities();
$this->registerTiles();
InventoryType::init();
Block::init();
Item::init();
@ -1561,7 +1596,6 @@ class Server{
set_exception_handler([$this, "exceptionHandler"]);
register_shutdown_function([$this, "crashDump"]);
register_shutdown_function([$this, "forceShutdown"]);
$this->pluginManager->loadPlugins($this->pluginPath);
@ -1577,20 +1611,17 @@ class Server{
LevelProviderManager::addProvider($this, Anvil::class);
LevelProviderManager::addProvider($this, McRegion::class);
if(extension_loaded("leveldb")){
$this->logger->debug("Enabling LevelDB support");
LevelProviderManager::addProvider($this, LevelDB::class);
}
Generator::addGenerator(Flat::class, "flat");
Generator::addGenerator(Normal::class, "normal");
Generator::addGenerator(Normal::class, "default");
//Temporal workaround, pthreads static property nullification test
if(PluginManager::$pluginParentTimer === null or Timings::$serverTickTimer === null){
$this->getLogger()->emergency("You are using an invalid pthreads version. Please update your binaries.");
kill(getmypid());
return;
}
foreach($this->getProperty("worlds", []) as $name => $worldSetting){
foreach((array) $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")));
@ -1647,7 +1678,7 @@ class Server{
}
/**
* @param $message
* @param $message
* @param Player[]|null $recipients
*
* @return int
@ -1697,6 +1728,9 @@ class Server{
foreach($players as $player){
$player->dataPacket($packet);
}
if(isset($packet->__encapsulatedPacket)){
unset($packet->__encapsulatedPacket);
}
}
@ -1759,7 +1793,7 @@ class Server{
*/
public function dispatchCommand(CommandSender $sender, $commandLine){
if(!($sender instanceof CommandSender)){
throw new \Exception("CommandSender is not valid");
throw new ServerException("CommandSender is not valid");
}
if($this->commandMap->dispatch($sender, $commandLine)){
@ -1810,6 +1844,9 @@ class Server{
$this->reloadWhitelist();
$this->operators->reload();
foreach($this->getIPBans()->getEntries() as $entry){
$this->blockAddress($entry->getName(), -1);
}
$this->pluginManager->registerInterface(PharPluginLoader::class);
$this->pluginManager->loadPlugins($this->pluginPath);
@ -1827,40 +1864,54 @@ class Server{
}
public function forceShutdown(){
$this->shutdown();
if($this->rcon instanceof RCON){
$this->rcon->stop();
if($this->hasStopped){
return;
}
if($this->getProperty("settings.upnp-forwarding", false) === true){
$this->logger->info("[UPnP] Removing port forward...");
UPnP::RemovePortForward($this->getPort());
try{
$this->hasStopped = true;
$this->shutdown();
if($this->rcon instanceof RCON){
$this->rcon->stop();
}
if($this->getProperty("settings.upnp-forwarding", false) === true){
$this->logger->info("[UPnP] Removing port forward...");
UPnP::RemovePortForward($this->getPort());
}
$this->pluginManager->disablePlugins();
foreach($this->players as $player){
$player->close(TextFormat::YELLOW . $player->getName() . " has left the game", $this->getProperty("settings.shutdown-message", "Server closed"));
}
foreach($this->getLevels() as $level){
$this->unloadLevel($level, true);
}
if($this->generationManager instanceof GenerationRequestManager){
$this->generationManager->shutdown();
}
HandlerList::unregisterAll();
$this->scheduler->cancelAllTasks();
$this->scheduler->mainThreadHeartbeat(PHP_INT_MAX);
$this->properties->save();
$this->console->kill();
foreach($this->interfaces as $interface){
$interface->shutdown();
}
}catch(\Exception $e){
$this->logger->emergency("Crashed while crashing, killing process");
@kill(getmypid());
}
$this->pluginManager->disablePlugins();
foreach($this->players as $player){
$player->close(TextFormat::YELLOW . $player->getName() . " has left the game", $this->getProperty("settings.shutdown-message", "Server closed"));
}
foreach($this->getLevels() as $level){
$this->unloadLevel($level, true);
}
if($this->generationManager instanceof GenerationRequestManager){
$this->generationManager->shutdown();
}
HandlerList::unregisterAll();
$this->scheduler->cancelAllTasks();
$this->scheduler->mainThreadHeartbeat(PHP_INT_MAX);
$this->properties->save();
$this->console->kill();
foreach($this->interfaces as $interface){
$interface->shutdown();
}
}
/**
@ -1873,6 +1924,9 @@ class Server{
}
foreach($this->getIPBans()->getEntries() as $entry){
$this->blockAddress($entry->getName(), -1);
}
if($this->getProperty("settings.send-usage", true) !== false){
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([$this, "sendUsage"]), 6000, 6000);
@ -1929,25 +1983,56 @@ class Server{
}
}
public function exceptionHandler(\Exception $e){
public function exceptionHandler(\Exception $e, $trace = null){
if($e === null){
return;
}
error_handler(E_ERROR, $e->getMessage(), $e->getFile(), $e->getLine(), [], $e->getTrace());
global $lastError;
if($trace === null){
$trace = $e->getTrace();
}
$errstr = $e->getMessage();
$errfile = $e->getFile();
$errno = $e->getCode();
$errline = $e->getLine();
$type = ($errno === E_ERROR or $errno === E_USER_ERROR) ? \LogLevel::ERROR : (($errno === E_USER_WARNING or $errno === E_WARNING) ? \LogLevel::WARNING : \LogLevel::NOTICE);
if(($pos = strpos($errstr, "\n")) !== false){
$errstr = substr($errstr, 0, $pos);
}
$errfile = cleanPath($errfile);
if($this->logger instanceof MainLogger){
$this->logger->logException($e, $trace);
}
$lastError = [
"type" => $type,
"message" => $errstr,
"fullFile" => $e->getFile(),
"file" => $errfile,
"line" => $errline,
"trace" => @getTrace(1, $trace)
];
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->isRunning = false;
$this->hasStopped = false;
ini_set("error_reporting", 0);
ini_set("memory_limit", -1); //Fix error dump not dumped on memory problems
$this->logger->emergency("An unrecoverable error has occurred and the server has crashed. Creating a crash dump");
$dump = new CrashDump($this);
@ -1955,40 +2040,46 @@ class Server{
if($this->getProperty("auto-report.enabled", true) !== false){
$report = true;
$plugin = $dump->getData()["plugin"];
if(is_string($plugin)){
$p = $this->pluginManager->getPlugin($plugin);
if($p instanceof Plugin and !($p->getPluginLoader() instanceof PharPluginLoader)){
return;
$report = false;
}
}elseif(\Phar::running(true) == ""){
return;
$report = false;
}
if($dump->getData()["error"]["type"] === "E_PARSE" or $dump->getData()["error"]["type"] === "E_COMPILE_ERROR"){
return;
$report = false;
}
$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($report){
$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.");
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.");
}
}
}
//$this->checkMemory();
//$dump .= "Memory Usage Tracking: \r\n" . chunk_split(base64_encode(gzdeflate(implode(";", $this->memoryStats), 9))) . "\r\n";
$this->forceShutdown();
@kill(getmypid());
exit(1);
}
public function __debugInfo(){
return get_class($this);
return [];
}
private function tickProcessor(){
@ -2006,7 +2097,14 @@ class Server{
//Do level ticks
foreach($this->getLevels() as $level){
$level->doTick($currentTick);
try{
$level->doTick($currentTick);
}catch(\Exception $e){
$this->logger->critical("Could not tick level " . $level->getName() . ": " . $e->getMessage());
if(\pocketmine\DEBUG > 1 and $this->logger instanceof MainLogger){
$this->logger->logException($e);
}
}
}
}
@ -2070,7 +2168,7 @@ class Server{
private function titleTick(){
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0 and \pocketmine\ANSI === true){
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() . " | Load ". $this->getTickUsage() . "%\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() . " | Load " . $this->getTickUsage() . "%\x07";
}
}
@ -2105,11 +2203,32 @@ class Server{
if(($this->tickCounter & 0b1111) === 0){
$this->titleTick();
if(isset($this->queryHandler) and ($this->tickCounter & 0b111111111) === 0){
$this->queryHandler->regenerateInfo();
try{
$this->queryHandler->regenerateInfo();
}catch(\Exception $e){
if($this->logger instanceof MainLogger){
$this->logger->logException($e);
}
}
}
}
Timings::$generationTimer->startTiming();
try{
$this->generationManager->process();
}catch(\Exception $e){
if($this->logger instanceof MainLogger){
$this->logger->logException($e);
}
}
Timings::$generationTimer->stopTiming();
if(($this->tickCounter % 100) === 0){
foreach($this->levels as $level){
$level->clearCache();
}
}
$this->generationManager->process();
Timings::$serverTickTimer->stopTiming();
@ -2129,4 +2248,22 @@ class Server{
return true;
}
private function registerEntities(){
Entity::registerEntity(Arrow::class);
Entity::registerEntity(DroppedItem::class);
Entity::registerEntity(FallingSand::class);
Entity::registerEntity(PrimedTNT::class);
Entity::registerEntity(Snowball::class);
Entity::registerEntity(Villager::class);
Entity::registerEntity(Zombie::class);
Entity::registerEntity(Human::class, true);
}
private function registerTiles(){
Tile::registerTile(Chest::class);
Tile::registerTile(Furnace::class);
Tile::registerTile(Sign::class);
}
}

View File

@ -24,8 +24,15 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class AcaciaWoodStairs extends Stair{
protected $id = self::ACACIA_WOOD_STAIRS;
public function __construct($meta = 0){
parent::__construct(self::ACACIA_WOOD_STAIRS, $meta, "Acacia Wood Stairs");
$this->meta = $meta;
}
public function getName(){
return "Acacia Wood Stairs";
}
public function getDrops(Item $item){

View File

@ -21,29 +21,45 @@
namespace pocketmine\block;
use pocketmine\item\Item;
/**
* 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(){
}
public function getName(){
return "Air";
}
public function isBreakable(Item $item){
return false;
}
public function canBeFlowedInto(){
return true;
}
public function canBeReplaced(){
return true;
}
public function canBePlaced(){
return false;
}
public function isSolid(){
return false;
}
public function getBoundingBox(){
return null;
}

View File

@ -28,19 +28,27 @@ use pocketmine\network\protocol\ChatPacket;
use pocketmine\Player;
class Bed extends Transparent{
public function __construct($type = 0){
parent::__construct(self::BED_BLOCK, $type, "Bed Block");
$this->isActivable = true;
$this->isFullBlock = false;
$this->hardness = 1;
protected $id = self::BED_BLOCK;
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getBoundingBox(){
if($this->boundingBox !== null){
return $this->boundingBox;
}
public function canBeActivated(){
return true;
}
return $this->boundingBox = new AxisAlignedBB(
public function getHardness(){
return 1;
}
public function getName(){
return "Bed Block";
}
protected function recalculateBoundingBox(){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
@ -57,7 +65,7 @@ class Bed extends Transparent{
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
if($player instanceof Player and !$isNight){
$pk = new ChatPacket;
$pk = new ChatPacket();
$pk->message = "You can only sleep at night";
$player->dataPacket($pk);
@ -71,17 +79,17 @@ class Bed extends Transparent{
if(($this->meta & 0x08) === 0x08){ //This is the Top part of bed
$b = $this;
}else{ //Bottom Part of Bed
if($blockNorth->getID() === $this->id and ($blockNorth->meta & 0x08) === 0x08){
if($blockNorth->getId() === $this->id and ($blockNorth->meta & 0x08) === 0x08){
$b = $blockNorth;
}elseif($blockSouth->getID() === $this->id and ($blockSouth->meta & 0x08) === 0x08){
}elseif($blockSouth->getId() === $this->id and ($blockSouth->meta & 0x08) === 0x08){
$b = $blockSouth;
}elseif($blockEast->getID() === $this->id and ($blockEast->meta & 0x08) === 0x08){
}elseif($blockEast->getId() === $this->id and ($blockEast->meta & 0x08) === 0x08){
$b = $blockEast;
}elseif($blockWest->getID() === $this->id and ($blockWest->meta & 0x08) === 0x08){
}elseif($blockWest->getId() === $this->id and ($blockWest->meta & 0x08) === 0x08){
$b = $blockWest;
}else{
if($player instanceof Player){
$pk = new ChatPacket;
$pk = new ChatPacket();
$pk->message = "This bed is incomplete";
$player->dataPacket($pk);
}
@ -91,7 +99,7 @@ class Bed extends Transparent{
}
if($player instanceof Player and $player->sleepOn($b) === false){
$pk = new ChatPacket;
$pk = new ChatPacket();
$pk->message = "This bed is occupied";
$player->dataPacket($pk);
}
@ -101,7 +109,7 @@ 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){
if($down->isTransparent() === false){
$faces = [
0 => 3,
1 => 4,
@ -111,7 +119,7 @@ class Bed extends Transparent{
$d = $player instanceof Player ? $player->getDirection() : 0;
$next = $this->getSide($faces[(($d + 3) % 4)]);
$downNext = $this->getSide(0);
if($next->isReplaceable === true and $downNext->isTransparent === false){
if($next->canBeReplaced() === true and $downNext->isTransparent() === false){
$meta = (($d + 3) % 4) & 0x03;
$this->getLevel()->setBlock($block, Block::get($this->id, $meta), true, true);
$this->getLevel()->setBlock($next, Block::get($this->id, $meta | 0x08), true, true);
@ -130,23 +138,23 @@ class Bed extends Transparent{
$blockWest = $this->getSide(4);
if(($this->meta & 0x08) === 0x08){ //This is the Top part of bed
if($blockNorth->getID() === $this->id and $blockNorth->meta !== 0x08){ //Checks if the block ID and meta are right
if($blockNorth->getId() === $this->id and $blockNorth->meta !== 0x08){ //Checks if the block ID and meta are right
$this->getLevel()->setBlock($blockNorth, new Air(), true, true);
}elseif($blockSouth->getID() === $this->id and $blockSouth->meta !== 0x08){
}elseif($blockSouth->getId() === $this->id and $blockSouth->meta !== 0x08){
$this->getLevel()->setBlock($blockSouth, new Air(), true, true);
}elseif($blockEast->getID() === $this->id and $blockEast->meta !== 0x08){
}elseif($blockEast->getId() === $this->id and $blockEast->meta !== 0x08){
$this->getLevel()->setBlock($blockEast, new Air(), true, true);
}elseif($blockWest->getID() === $this->id and $blockWest->meta !== 0x08){
}elseif($blockWest->getId() === $this->id and $blockWest->meta !== 0x08){
$this->getLevel()->setBlock($blockWest, new Air(), true, true);
}
}else{ //Bottom Part of Bed
if($blockNorth->getID() === $this->id and ($blockNorth->meta & 0x08) === 0x08){
if($blockNorth->getId() === $this->id and ($blockNorth->meta & 0x08) === 0x08){
$this->getLevel()->setBlock($blockNorth, new Air(), true, true);
}elseif($blockSouth->getID() === $this->id and ($blockSouth->meta & 0x08) === 0x08){
}elseif($blockSouth->getId() === $this->id and ($blockSouth->meta & 0x08) === 0x08){
$this->getLevel()->setBlock($blockSouth, new Air(), true, true);
}elseif($blockEast->getID() === $this->id and ($blockEast->meta & 0x08) === 0x08){
}elseif($blockEast->getId() === $this->id and ($blockEast->meta & 0x08) === 0x08){
$this->getLevel()->setBlock($blockEast, new Air(), true, true);
}elseif($blockWest->getID() === $this->id and ($blockWest->meta & 0x08) === 0x08){
}elseif($blockWest->getId() === $this->id and ($blockWest->meta & 0x08) === 0x08){
$this->getLevel()->setBlock($blockWest, new Air(), true, true);
}
}

View File

@ -24,10 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Bedrock extends Solid{
protected $id = self::BEDROCK;
public function __construct(){
parent::__construct(self::BEDROCK, 0, "Bedrock");
$this->breakable = false;
$this->hardness = 18000000;
}
public function getName(){
return "Bedrock";
}
public function getHardness(){
return 18000000;
}
public function isBreakable(Item $item){

View File

@ -24,8 +24,15 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Beetroot extends Crops{
protected $id = self::BEETROOT_BLOCK;
public function __construct($meta = 0){
parent::__construct(self::BEETROOT_BLOCK, $meta, "Beetroot Block");
$this->meta = $meta;
}
public function getName(){
return "Beetroot Block";
}
public function getDrops(Item $item){

View File

@ -24,8 +24,15 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class BirchWoodStairs extends Stair{
protected $id = self::BIRCH_WOOD_STAIRS;
public function __construct($meta = 0){
parent::__construct(self::BIRCH_WOOD_STAIRS, $meta, "Birch Wood Stairs");
$this->meta = $meta;
}
public function getName(){
return "Birch Wood Stairs";
}
public function getDrops(Item $item){

View File

@ -144,6 +144,7 @@ class Block extends Position implements Metadatable{
const SUGARCANE_BLOCK = 83;
const FENCE = 85;
const FENCE_OAK = 85;
const PUMPKIN = 86;
const NETHERRACK = 87;
const SOUL_SAND = 88;
@ -179,7 +180,7 @@ class Block extends Position implements Metadatable{
const NETHER_BRICKS_STAIRS = 114;
const END_PORTAL = 120;
const END_PORTAL_FRAME = 120;
const END_STONE = 121;
const SANDSTONE_STAIRS = 128;
@ -228,6 +229,19 @@ class Block extends Position implements Metadatable{
const HARDENED_CLAY = 172;
const COAL_BLOCK = 173;
const DOUBLE_PLANT = 175;
const FENCE_GATE_SPRUCE = 183;
const FENCE_GATE_BIRCH = 184;
const FENCE_GATE_JUNGLE = 185;
const FENCE_GATE_DARK_OAK = 186;
const FENCE_GATE_ACACIA = 187;
const FENCE_SPRUCE = 188;
const FENCE_BIRCH = 189;
const FENCE_JUNGLE = 190;
const FENCE_DARK_OAK = 191;
const FENCE_ACACIA = 192;
const PODZOL = 243;
const BEETROOT_BLOCK = 244;
const STONECUTTER = 245;
@ -354,7 +368,16 @@ class Block extends Position implements Metadatable{
[Item::WOODEN_DOOR, 0],
[Item::TRAPDOOR, 0],
[Item::FENCE, 0],
[Item::FENCE_SPRUCE, 0],
[Item::FENCE_BIRCH, 0],
[Item::FENCE_DARK_OAK, 0],
[Item::FENCE_JUNGLE, 0],
[Item::FENCE_GATE, 0],
[Item::FENCE_GATE_BIRCH, 0],
[Item::FENCE_GATE_SPRUCE, 0],
[Item::FENCE_GATE_DARK_OAK, 0],
[Item::FENCE_GATE_JUNGLE, 0],
[Item::FENCE_GATE_ACACIA, 0],
[Item::IRON_BARS, 0],
[Item::BED, 0],
[Item::BOOKSHELF, 0],
@ -505,170 +528,247 @@ class Block extends Position implements Metadatable{
];
/** @var Block[] */
public static $list = [];
/** @var \SplFixedArray */
public static $list = null;
/** @var \SplFixedArray */
public static $fullList = null;
/** @var \SplFixedArray */
public static $light = null;
/** @var \SplFixedArray */
public static $lightFilter = null;
/** @var \SplFixedArray */
public static $solid = null;
/** @var \SplFixedArray */
public static $hardness = null;
/** @var \SplFixedArray */
public static $transparent = null;
protected $id;
protected $meta;
protected $name = "Unknown";
protected $breakTime = 0.20;
protected $hardness = 10;
protected $meta = 0;
/** @var AxisAlignedBB */
protected $boundingBox = null;
public $hasEntityCollision = false;
public $isActivable = false;
public $breakable = true;
public $isFlowable = false;
public $isSolid = true;
public $isTransparent = false;
public $isReplaceable = false;
public $isPlaceable = true;
public $hasPhysics = false;
public $isLiquid = false;
public $isFullBlock = true;
public $x = 0;
public $y = 0;
public $z = 0;
public $frictionFactor = 0.6;
/**
* Backwards-compatibility with old way to define block properties
*
* @deprecated
*
* @param string $key
*
* @return mixed
*/
public function __get($key){
static $map = [
"hardness" => "getHardness",
"lightLevel" => "getLightLevel",
"frictionFactor" => "getFrictionFactor",
"name" => "getName",
"isPlaceable" => "canBePlaced",
"isReplaceable" => "canBeReplaced",
"isTransparent" => "isTransparent",
"isSolid" => "isSolid",
"isFlowable" => "canBeFlowedInto",
"isActivable" => "canBeActivated",
"hasEntityCollision" => "hasEntityCollision"
];
return isset($map[$key]) ? $this->{$map[$key]}() : null;
}
public static function init(){
if(count(self::$list) === 0){
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,
if(self::$list === null){
self::$list = new \SplFixedArray(256);
self::$fullList = new \SplFixedArray(4096);
self::$light = new \SplFixedArray(256);
self::$lightFilter = new \SplFixedArray(256);
self::$solid = new \SplFixedArray(256);
self::$hardness = new \SplFixedArray(256);
self::$transparent = new \SplFixedArray(256);
self::$list[self::AIR] = Air::class;
self::$list[self::STONE] = Stone::class;
self::$list[self::GRASS] = Grass::class;
self::$list[self::DIRT] = Dirt::class;
self::$list[self::COBBLESTONE] = Cobblestone::class;
self::$list[self::PLANKS] = Planks::class;
self::$list[self::SAPLING] = Sapling::class;
self::$list[self::BEDROCK] = Bedrock::class;
self::$list[self::WATER] = Water::class;
self::$list[self::STILL_WATER] = StillWater::class;
self::$list[self::LAVA] = Lava::class;
self::$list[self::STILL_LAVA] = StillLava::class;
self::$list[self::SAND] = Sand::class;
self::$list[self::GRAVEL] = Gravel::class;
self::$list[self::GOLD_ORE] = GoldOre::class;
self::$list[self::IRON_ORE] = IronOre::class;
self::$list[self::COAL_ORE] = CoalOre::class;
self::$list[self::WOOD] = Wood::class;
self::$list[self::LEAVES] = Leaves::class;
self::$list[self::SPONGE] = Sponge::class;
self::$list[self::GLASS] = Glass::class;
self::$list[self::LAPIS_ORE] = LapisOre::class;
self::$list[self::LAPIS_BLOCK] = Lapis::class;
self::$list[self::SANDSTONE] = Sandstone::class;
self::$list[self::BED_BLOCK] = Bed::class;
self::$list[self::COBWEB] = Cobweb::class;
self::$list[self::TALL_GRASS] = TallGrass::class;
self::$list[self::DEAD_BUSH] = DeadBush::class;
self::$list[self::WOOL] = Wool::class;
self::$list[self::DANDELION] = Dandelion::class;
self::$list[self::POPPY] = Poppy::class;
self::$list[self::BROWN_MUSHROOM] = BrownMushroom::class;
self::$list[self::RED_MUSHROOM] = RedMushroom::class;
self::$list[self::GOLD_BLOCK] = Gold::class;
self::$list[self::IRON_BLOCK] = Iron::class;
self::$list[self::DOUBLE_SLAB] = DoubleSlab::class;
self::$list[self::SLAB] = Slab::class;
self::$list[self::BRICKS_BLOCK] = Bricks::class;
self::$list[self::TNT] = TNT::class;
self::$list[self::BOOKSHELF] = Bookshelf::class;
self::$list[self::MOSS_STONE] = MossStone::class;
self::$list[self::OBSIDIAN] = Obsidian::class;
self::$list[self::TORCH] = Torch::class;
self::$list[self::FIRE] = Fire::class;
self::$list[self::MONSTER_SPAWNER] = MonsterSpawner::class;
self::$list[self::WOOD_STAIRS] = WoodStairs::class;
self::$list[self::CHEST] = Chest::class;
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::$list[self::DIAMOND_ORE] = DiamondOre::class;
self::$list[self::DIAMOND_BLOCK] = Diamond::class;
self::$list[self::WORKBENCH] = Workbench::class;
self::$list[self::WHEAT_BLOCK] = Wheat::class;
self::$list[self::FARMLAND] = Farmland::class;
self::$list[self::FURNACE] = Furnace::class;
self::$list[self::BURNING_FURNACE] = BurningFurnace::class;
self::$list[self::SIGN_POST] = SignPost::class;
self::$list[self::WOOD_DOOR_BLOCK] = WoodDoor::class;
self::$list[self::LADDER] = Ladder::class;
self::COBBLESTONE_STAIRS => CobblestoneStairs::class,
self::WALL_SIGN => WallSign::class,
self::$list[self::COBBLESTONE_STAIRS] = CobblestoneStairs::class;
self::$list[self::WALL_SIGN] = WallSign::class;
self::IRON_DOOR_BLOCK => IronDoor::class,
self::REDSTONE_ORE => RedstoneOre::class,
self::GLOWING_REDSTONE_ORE => GlowingRedstoneOre::class,
self::$list[self::IRON_DOOR_BLOCK] = IronDoor::class;
self::$list[self::REDSTONE_ORE] = RedstoneOre::class;
self::$list[self::GLOWING_REDSTONE_ORE] = GlowingRedstoneOre::class;
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::$list[self::SNOW_LAYER] = SnowLayer::class;
self::$list[self::ICE] = Ice::class;
self::$list[self::SNOW_BLOCK] = Snow::class;
self::$list[self::CACTUS] = Cactus::class;
self::$list[self::CLAY_BLOCK] = Clay::class;
self::$list[self::SUGARCANE_BLOCK] = Sugarcane::class;
self::FENCE => Fence::class,
self::PUMPKIN => Pumpkin::class,
self::NETHERRACK => Netherrack::class,
self::SOUL_SAND => SoulSand::class,
self::GLOWSTONE_BLOCK => Glowstone::class,
self::$list[self::FENCE] = Fence::class;
self::$list[self::PUMPKIN] = Pumpkin::class;
self::$list[self::NETHERRACK] = Netherrack::class;
self::$list[self::SOUL_SAND] = SoulSand::class;
self::$list[self::GLOWSTONE_BLOCK] = Glowstone::class;
self::LIT_PUMPKIN => LitPumpkin::class,
self::CAKE_BLOCK => Cake::class,
self::$list[self::LIT_PUMPKIN] = LitPumpkin::class;
self::$list[self::CAKE_BLOCK] = Cake::class;
self::TRAPDOOR => Trapdoor::class,
self::$list[self::TRAPDOOR] = Trapdoor::class;
self::STONE_BRICKS => StoneBricks::class,
self::$list[self::STONE_BRICKS] = StoneBricks::class;
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::VINE => Vine::class,
self::FENCE_GATE => FenceGate::class,
self::BRICK_STAIRS => BrickStairs::class,
self::STONE_BRICK_STAIRS => StoneBrickStairs::class,
self::$list[self::IRON_BARS] = IronBars::class;
self::$list[self::GLASS_PANE] = GlassPane::class;
self::$list[self::MELON_BLOCK] = Melon::class;
self::$list[self::PUMPKIN_STEM] = PumpkinStem::class;
self::$list[self::MELON_STEM] = MelonStem::class;
self::$list[self::VINE] = Vine::class;
self::$list[self::FENCE_GATE] = FenceGate::class;
self::$list[self::BRICK_STAIRS] = BrickStairs::class;
self::$list[self::STONE_BRICK_STAIRS] = StoneBrickStairs::class;
self::MYCELIUM => Mycelium::class,
self::NETHER_BRICKS => NetherBrick::class,
self::$list[self::MYCELIUM] = Mycelium::class;
self::$list[self::NETHER_BRICKS] = NetherBrick::class;
self::NETHER_BRICKS_STAIRS => NetherBrickStairs::class,
self::$list[self::NETHER_BRICKS_STAIRS] = NetherBrickStairs::class;
self::END_PORTAL => EndPortal::class,
self::END_STONE => EndStone::class,
self::SANDSTONE_STAIRS => SandstoneStairs::class,
self::EMERALD_ORE => EmeraldOre::class,
self::$list[self::END_PORTAL_FRAME] = EndPortalFrame::class;
self::$list[self::END_STONE] = EndStone::class;
self::$list[self::SANDSTONE_STAIRS] = SandstoneStairs::class;
self::$list[self::EMERALD_ORE] = EmeraldOre::class;
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::$list[self::EMERALD_BLOCK] = Emerald::class;
self::$list[self::SPRUCE_WOOD_STAIRS] = SpruceWoodStairs::class;
self::$list[self::BIRCH_WOOD_STAIRS] = BirchWoodStairs::class;
self::$list[self::JUNGLE_WOOD_STAIRS] = JungleWoodStairs::class;
self::$list[self::STONE_WALL] = StoneWall::class;
self::CARROT_BLOCK => Carrot::class,
self::POTATO_BLOCK => Potato::class,
self::$list[self::CARROT_BLOCK] = Carrot::class;
self::$list[self::POTATO_BLOCK] = Potato::class;
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::$list[self::QUARTZ_BLOCK] = Quartz::class;
self::$list[self::QUARTZ_STAIRS] = QuartzStairs::class;
self::$list[self::DOUBLE_WOOD_SLAB] = DoubleWoodSlab::class;
self::$list[self::WOOD_SLAB] = WoodSlab::class;
self::$list[self::STAINED_CLAY] = StainedClay::class;
self::LEAVES2 => Leaves2::class,
self::WOOD2 => Wood2::class,
self::ACACIA_WOOD_STAIRS => AcaciaWoodStairs::class,
self::DARK_OAK_WOOD_STAIRS => DarkOakWoodStairs::class,
self::$list[self::LEAVES2] = Leaves2::class;
self::$list[self::WOOD2] = Wood2::class;
self::$list[self::ACACIA_WOOD_STAIRS] = AcaciaWoodStairs::class;
self::$list[self::DARK_OAK_WOOD_STAIRS] = DarkOakWoodStairs::class;
self::HAY_BALE => HayBale::class,
self::CARPET => Carpet::class,
self::HARDENED_CLAY => HardenedClay::class,
self::COAL_BLOCK => Coal::class,
self::$list[self::HAY_BALE] = HayBale::class;
self::$list[self::CARPET] = Carpet::class;
self::$list[self::HARDENED_CLAY] = HardenedClay::class;
self::$list[self::COAL_BLOCK] = Coal::class;
self::PODZOL => Podzol::class,
self::BEETROOT_BLOCK => Beetroot::class,
self::STONECUTTER => Stonecutter::class,
self::GLOWING_OBSIDIAN => GlowingObsidian::class,
self::NETHER_REACTOR => NetherReactor::class,
];
self::$list[self::DOUBLE_PLANT] = DoublePlant::class;
self::$list[self::FENCE_GATE_SPRUCE] = FenceGateSpruce::class;
self::$list[self::FENCE_GATE_BIRCH] = FenceGateBirch::class;
self::$list[self::FENCE_GATE_JUNGLE] = FenceGateJungle::class;
self::$list[self::FENCE_GATE_DARK_OAK] = FenceGateDarkOak::class;
self::$list[self::FENCE_GATE_ACACIA] = FenceGateAcacia::class;
self::$list[self::FENCE_SPRUCE] = FenceSpruce::class;
self::$list[self::FENCE_BIRCH] = FenceBirch::class;
self::$list[self::FENCE_DARK_OAK] = FenceDarkOak::class;
self::$list[self::FENCE_JUNGLE] = FenceJungle::class;
self::$list[self::FENCE_ACACIA] = FenceAcacia::class;
self::$list[self::PODZOL] = Podzol::class;
self::$list[self::BEETROOT_BLOCK] = Beetroot::class;
self::$list[self::STONECUTTER] = Stonecutter::class;
self::$list[self::GLOWING_OBSIDIAN] = GlowingObsidian::class;
self::$list[self::NETHER_REACTOR] = NetherReactor::class;
foreach(self::$list as $id => $class){
if($class !== null){
/** @var Block $block */
$block = new $class();
for($data = 0; $data < 16; ++$data){
self::$fullList[($id << 4) | $data] = new $class($data);
}
self::$solid[$id] = $block->isSolid();
self::$transparent[$id] = $block->isTransparent();
self::$hardness[$id] = $block->getHardness();
self::$light[$id] = $block->getLightLevel();
if($block->isSolid()){
if($block->isTransparent()){
if($block instanceof Liquid or $block instanceof Ice){
self::$lightFilter[$id] = 2;
}else{
self::$lightFilter[$id] = 1;
}
}else{
self::$lightFilter[$id] = 15;
}
}else{
self::$lightFilter[$id] = 1;
}
}else{
self::$lightFilter[$id] = 1;
for($data = 0; $data < 16; ++$data){
self::$fullList[($id << 4) | $data] = new Block($id, $data);
}
}
}
}
}
@ -680,14 +780,18 @@ class Block extends Position implements Metadatable{
* @return Block
*/
public static function get($id, $meta = 0, Position $pos = null){
if(isset(self::$list[$id])){
try{
$block = self::$list[$id];
$block = new $block($meta);
}else{
if($block !== null){
$block = new $block($meta);
}else{
$block = new Block($id, $meta);
}
}catch(\RuntimeException $e){
$block = new Block($id, $meta);
}
if($pos instanceof Position){
if($pos !== null){
$block->x = $pos->x;
$block->y = $pos->y;
$block->z = $pos->z;
@ -698,14 +802,12 @@ class Block extends Position implements Metadatable{
}
/**
* @param int $id
* @param int $meta
* @param string $name
* @param int $id
* @param int $meta
*/
public function __construct($id, $meta = 0, $name = "Unknown"){
public function __construct($id, $meta = 0){
$this->id = (int) $id;
$this->meta = (int) $meta;
$this->name = $name;
}
/**
@ -734,7 +836,7 @@ class Block extends Position implements Metadatable{
* @return bool
*/
public function isBreakable(Item $item){
return $this->breakable;
return true;
}
/**
@ -768,27 +870,92 @@ class Block extends Position implements Metadatable{
* @return bool
*/
public function onActivate(Item $item, Player $player = null){
return $this->isActivable;
return false;
}
/**
* @return int
*/
final public function getHardness(){
return $this->hardness;
public function getHardness(){
return 10;
}
/**
* @return float
*/
public function getFrictionFactor(){
return 0.6;
}
/**
* @return int 0-15
*/
public function getLightLevel(){
return 0;
}
/**
* AKA: Block->isPlaceable
*
* @return bool
*/
public function canBePlaced(){
return true;
}
/**
* AKA: Block->canBeReplaced()
*
* @return bool
*/
public function canBeReplaced(){
return false;
}
/**
* @return bool
*/
public function isTransparent(){
return false;
}
public function isSolid(){
return true;
}
/**
* AKA: Block->isFlowable
*
* @return bool
*/
public function canBeFlowedInto(){
return false;
}
/**
* AKA: Block->isActivable
*
* @return bool
*/
public function canBeActivated(){
return false;
}
public function hasEntityCollision(){
return false;
}
/**
* @return string
*/
final public function getName(){
return $this->name;
public function getName(){
return "Unknown";
}
/**
* @return int
*/
final public function getID(){
final public function getId(){
return $this->id;
}
@ -807,7 +974,7 @@ class Block extends Position implements Metadatable{
* @param int $meta
*/
final public function setDamage($meta){
$this->meta = $meta & 0x0F;
$this->meta = $meta & 0x0f;
}
/**
@ -820,7 +987,6 @@ class Block extends Position implements Metadatable{
$this->y = (int) $v->y;
$this->z = (int) $v->z;
$this->level = $v->level;
$this->boundingBox = null;
}
/**
@ -848,7 +1014,7 @@ class Block extends Position implements Metadatable{
* @return float
*/
public function getBreakTime(Item $item){
return $this->breakTime;
return 0.20;
}
/**
@ -860,19 +1026,18 @@ class Block extends Position implements Metadatable{
* @return Block
*/
public function getSide($side, $step = 1){
$v = parent::getSide($side, $step);
if($this->isValid()){
return $this->getLevel()->getBlock($v);
return $this->getLevel()->getBlock(Vector3::getSide($side, $step));
}
return Block::get(Item::AIR, 0, $v);
return Block::get(Item::AIR, 0, new Position($v->x, $v->y, $v->z, null));
}
/**
* @return string
*/
final public function __toString(){
return "Block " . $this->name . " (" . $this->id . ":" . $this->meta . ")";
public function __toString(){
return "Block[" . $this->getName() . "] (" . $this->id . ":" . $this->meta . ")";
}
/**
@ -901,9 +1066,16 @@ class Block extends Position implements Metadatable{
public function getBoundingBox(){
if($this->boundingBox !== null){
return $this->boundingBox;
}else{
return $this->boundingBox = $this->recalculateBoundingBox();
}
}
return $this->boundingBox = new AxisAlignedBB(
/**
* @return AxisAlignedBB
*/
protected function recalculateBoundingBox(){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,

View File

@ -23,9 +23,19 @@ namespace pocketmine\block;
class Bookshelf extends Solid{
protected $id = self::BOOKSHELF;
public function __construct(){
parent::__construct(self::BOOKSHELF, 0, "Bookshelf");
$this->hardness = 7.5;
}
public function getName(){
return "Bookshelf";
}
public function getHardness(){
return 7.5;
}
}

View File

@ -23,8 +23,15 @@ namespace pocketmine\block;
class BrickStairs extends Stair{
protected $id = self::BRICK_STAIRS;
public function __construct($meta = 0){
parent::__construct(self::BRICK_STAIRS, $meta, "Brick Stairs");
$this->meta = $meta;
}
public function getName(){
return "Brick Stairs";
}
}

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Bricks extends Solid{
protected $id = self::BRICKS_BLOCK;
public function __construct(){
parent::__construct(self::BRICKS_BLOCK, 0, "Bricks");
$this->hardness = 30;
}
public function getHardness(){
return 30;
}
public function getName(){
return "Bricks";
}
public function getBreakTime(Item $item){

View File

@ -26,14 +26,24 @@ use pocketmine\level\Level;
use pocketmine\Player;
class BrownMushroom extends Flowable{
public function __construct(){
parent::__construct(self::BROWN_MUSHROOM, 0, "Brown Mushroom");
$this->hardness = 0;
protected $id = self::BROWN_MUSHROOM;
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getName(){
return "Brown Mushroom";
}
public function getLightLevel(){
return 1;
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent === true){
if($this->getSide(0)->isTransparent() === true){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
@ -45,7 +55,7 @@ class BrownMushroom extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->isTransparent === false){
if($down->isTransparent() === false){
$this->getLevel()->setBlock($block, $this, true, true);
return true;

View File

@ -32,10 +32,27 @@ use pocketmine\tile\Furnace;
use pocketmine\tile\Tile;
class BurningFurnace extends Solid{
protected $id = self::BURNING_FURNACE;
public function __construct($meta = 0){
parent::__construct(self::BURNING_FURNACE, $meta, "Burning Furnace");
$this->isActivable = true;
$this->hardness = 17.5;
$this->meta = $meta;
}
public function getName(){
return "Burning Furnace";
}
public function canBeActivated(){
return true;
}
public function getHardness(){
return 17.5;
}
public function getLightLevel(){
return 13;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
@ -55,7 +72,7 @@ class BurningFurnace extends Solid{
new Int("z", $this->z)
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
new Furnace($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
Tile::createTile("Furnace", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
return true;
}
@ -81,7 +98,7 @@ class BurningFurnace extends Solid{
new Int("z", $this->z)
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$furnace = new Furnace($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
$furnace = Tile::createTile("Furnace", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
}
if(($player->getGamemode() & 0x01) === 0x01){

View File

@ -28,26 +28,33 @@ use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3 as Vector3;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\Server;
class Cactus extends Transparent{
public $hasEntityCollision = true;
protected $id = self::CACTUS;
public function __construct($meta = 0){
parent::__construct(self::CACTUS, $meta, "Cactus");
$this->isFullBlock = false;
$this->hardness = 2;
$this->meta = $meta;
}
public function getBoundingBox(){
if($this->boundingBox !== null){
return $this->boundingBox;
}
public function getHardness(){
return 2;
}
return $this->boundingBox = new AxisAlignedBB(
public function hasEntityCollision(){
return true;
}
public function getName(){
return "Cactus";
}
protected function recalculateBoundingBox(){
return new AxisAlignedBB(
$this->x + 0.0625,
$this->y,
$this->z + 0.0625,
@ -59,16 +66,13 @@ class Cactus extends Transparent{
public function onEntityCollide(Entity $entity){
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
Server::getInstance()->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$entity->attack($ev->getFinalDamage(), $ev);
}
$entity->attack($ev->getFinalDamage(), $ev);
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(0);
if($down->getID() !== self::SAND and $down->getID() !== self::CACTUS){
if($down->getId() !== self::SAND and $down->getId() !== self::CACTUS){
$this->getLevel()->useBreakOn($this);
}else{
for($side = 2; $side <= 5; ++$side){
@ -79,11 +83,11 @@ class Cactus extends Transparent{
}
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if($this->getSide(0)->getID() !== self::CACTUS){
if($this->getSide(0)->getId() !== self::CACTUS){
if($this->meta == 0x0F){
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlock(new Vector3($this->x, $this->y + $y, $this->z));
if($b->getID() === self::AIR){
if($b->getId() === self::AIR){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, new Cactus()));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($b, $ev->getNewState(), true);
@ -104,12 +108,12 @@ class Cactus extends Transparent{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::SAND or $down->getID() === self::CACTUS){
if($down->getId() === self::SAND or $down->getId() === self::CACTUS){
$block0 = $this->getSide(2);
$block1 = $this->getSide(3);
$block2 = $this->getSide(4);
$block3 = $this->getSide(5);
if($block0->isTransparent === true and $block1->isTransparent === true and $block2->isTransparent === true and $block3->isTransparent === true){
if($block0->isTransparent() === true and $block1->isTransparent() === true and $block2->isTransparent() === true and $block3->isTransparent() === true){
$this->getLevel()->setBlock($this, $this, true);
return true;

View File

@ -29,22 +29,30 @@ use pocketmine\Player;
use pocketmine\Server;
class Cake extends Transparent{
protected $id = self::CAKE_BLOCK;
public function __construct($meta = 0){
parent::__construct(self::CAKE_BLOCK, 0, "Cake Block");
$this->isFullBlock = false;
$this->isActivable = true;
$this->meta = $meta & 0x07;
$this->hardness = 2.5;
$this->meta = $meta;
}
public function getBoundingBox(){
if($this->boundingBox !== null){
return $this->boundingBox;
}
public function canBeActivated(){
return true;
}
public function getHardness(){
return 2.5;
}
public function getName(){
return "Cake Block";
}
protected function recalculateBoundingBox(){
$f = (1 + $this->getDamage() * 2) / 16;
return $this->boundingBox = new AxisAlignedBB(
return new AxisAlignedBB(
$this->x + $f,
$this->y,
$this->z + 0.0625,
@ -56,7 +64,7 @@ class Cake extends Transparent{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() !== self::AIR){
if($down->getId() !== self::AIR){
$this->getLevel()->setBlock($block, $this, true, true);
return true;
@ -67,7 +75,7 @@ class Cake extends Transparent{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->getID() === self::AIR){ //Replace with common break method
if($this->getSide(0)->getId() === self::AIR){ //Replace with common break method
$this->getLevel()->setBlock($this, new Air(), true);
return Level::BLOCK_UPDATE_NORMAL;

View File

@ -27,9 +27,19 @@ use pocketmine\math\AxisAlignedBB;
use pocketmine\Player;
class Carpet extends Flowable{
protected $id = self::CARPET;
public function __construct($meta = 0){
parent::__construct(self::CARPET, $meta, "Carpet");
$names = [
$this->meta = $meta;
}
public function isSolid(){
return true;
}
public function getName(){
static $names = [
0 => "White Carpet",
1 => "Orange Carpet",
2 => "Magenta Carpet",
@ -47,18 +57,12 @@ class Carpet extends Flowable{
14 => "Red Carpet",
15 => "Black Carpet",
];
$this->name = $names[$this->meta];
$this->hardness = 0;
$this->isFullBlock = false;
$this->isSolid = true;
return $names[$this->meta & 0x0f];
}
public function getBoundingBox(){
if($this->boundingBox !== null){
return $this->boundingBox;
}
protected function recalculateBoundingBox(){
return $this->boundingBox = new AxisAlignedBB(
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
@ -70,7 +74,7 @@ class Carpet extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() !== self::AIR){
if($down->getId() !== self::AIR){
$this->getLevel()->setBlock($block, $this, true, true);
return true;
@ -81,7 +85,7 @@ class Carpet extends Flowable{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->getID() === self::AIR){
if($this->getSide(0)->getId() === self::AIR){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;

View File

@ -24,8 +24,15 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Carrot extends Crops{
protected $id = self::CARROT_BLOCK;
public function __construct($meta = 0){
parent::__construct(self::CARROT_BLOCK, $meta, "Carrot Block");
$this->meta = $meta;
}
public function getName(){
return "Carrot Block";
}
public function getDrops(Item $item){

View File

@ -34,20 +34,26 @@ use pocketmine\tile\Tile;
class Chest extends Transparent{
const SLOTS = 27;
protected $id = self::CHEST;
public function __construct($meta = 0){
parent::__construct(self::CHEST, $meta, "Chest");
$this->isActivable = true;
$this->hardness = 15;
$this->meta = $meta;
}
public function getBoundingBox(){
if($this->boundingBox !== null){
return $this->boundingBox;
}
public function canBeActivated(){
return true;
}
return $this->boundingBox = new AxisAlignedBB(
public function getHardness(){
return 15;
}
public function getName(){
return "Chest";
}
protected function recalculateBoundingBox(){
return new AxisAlignedBB(
$this->x + 0.0625,
$this->y,
$this->z + 0.0625,
@ -65,7 +71,7 @@ class Chest extends Transparent{
3 => 3,
];
$chest = false;
$chest = null;
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
for($side = 2; $side <= 5; ++$side){
@ -93,9 +99,9 @@ class Chest extends Transparent{
new Int("z", $this->z)
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$tile = new TileChest($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
$tile = Tile::createTile("Chest", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
if($chest instanceof TileChest){
if($chest instanceof TileChest and $tile instanceof TileChest){
$chest->pairWith($tile);
$tile->pairWith($chest);
}
@ -116,7 +122,7 @@ class Chest extends Transparent{
public function onActivate(Item $item, Player $player = null){
if($player instanceof Player){
$top = $this->getSide(1);
if($top->isTransparent !== true){
if($top->isTransparent() !== true){
return true;
}
@ -133,11 +139,11 @@ class Chest extends Transparent{
new Int("z", $this->z)
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$chest = new TileChest($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
$chest = Tile::createTile("Chest", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
}
if(($player->gamemode & 0x01) === 0x01){
if($player->isCreative()){
return true;
}
$player->addWindow($chest->getInventory());

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Clay extends Solid{
protected $id = self::CLAY_BLOCK;
public function __construct(){
parent::__construct(self::CLAY_BLOCK, 0, "Clay Block");
$this->hardness = 3;
}
public function getHardness(){
return 3;
}
public function getName(){
return "Clay Block";
}
public function getDrops(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Coal extends Solid{
protected $id = self::COAL_BLOCK;
public function __construct(){
parent::__construct(self::COAL_BLOCK, 0, "Coal Block");
$this->hardness = 30;
}
public function getHardness(){
return 30;
}
public function getName(){
return "Coal Block";
}
public function getBreakTime(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class CoalOre extends Solid{
protected $id = self::COAL_ORE;
public function __construct(){
parent::__construct(self::COAL_ORE, 0, "Coal Ore");
$this->hardness = 15;
}
public function getHardness(){
return 15;
}
public function getName(){
return "Coal Ore";
}
public function getBreakTime(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Cobblestone extends Solid{
protected $id = self::COBBLESTONE;
public function __construct(){
parent::__construct(self::COBBLESTONE, 0, "Cobblestone");
$this->hardness = 30;
}
public function getName(){
return "Cobblestone";
}
public function getHardness(){
return 30;
}
public function getBreakTime(Item $item){

View File

@ -23,8 +23,15 @@ namespace pocketmine\block;
class CobblestoneStairs extends Stair{
protected $id = self::COBBLESTONE_STAIRS;
public function __construct($meta = 0){
parent::__construct(self::COBBLESTONE_STAIRS, $meta, "Cobblestone Stairs");
$this->meta = $meta;
}
public function getName(){
return "Cobblestone Stairs";
}
}

View File

@ -26,13 +26,22 @@ use pocketmine\item\Item;
class Cobweb extends Flowable{
public $hasEntityCollision = true;
protected $id = self::COBWEB;
public function __construct(){
parent::__construct(self::COBWEB, 0, "Cobweb");
$this->isSolid = true;
$this->isFullBlock = false;
$this->hardness = 25;
}
public function hasEntityCollision(){
return true;
}
public function getName(){
return "Cobweb";
}
public function getHardness(){
return 25;
}
public function onEntityCollide(Entity $entity){
@ -40,6 +49,7 @@ class Cobweb extends Flowable{
}
public function getDrops(Item $item){
//TODO: correct drops
return [];
}
}

View File

@ -29,17 +29,13 @@ use pocketmine\Server;
abstract class Crops extends Flowable{
public $isActivable = true;
public $hardness = 0;
public function getBoundingBox(){
return null;
public function canBeActivated(){
return true;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
if($down->getId() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, true);
return true;
@ -50,7 +46,7 @@ abstract class Crops extends Flowable{
public function onActivate(Item $item, Player $player = null){
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
$block = clone $this;
$block->meta += mt_rand(2, 5);
if($block->meta > 7){
@ -73,7 +69,7 @@ abstract class Crops extends Flowable{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent === true){
if($this->getSide(0)->isTransparent() === true){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}

View File

@ -26,19 +26,21 @@ use pocketmine\level\Level;
use pocketmine\Player;
class Dandelion extends Flowable{
protected $id = self::DANDELION;
public function __construct(){
parent::__construct(self::DANDELION, 0, "Dandelion");
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
public function getName(){
return "Dandelion";
}
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){
if($down->getId() === 2 or $down->getId() === 3 or $down->getId() === 60){
$this->getLevel()->setBlock($block, $this, true, true);
return true;
@ -49,7 +51,7 @@ class Dandelion extends Flowable{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent === true){
if($this->getSide(0)->isTransparent() === true){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;

View File

@ -24,8 +24,15 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class DarkOakWoodStairs extends Stair{
protected $id = self::DARK_OAK_WOOD_STAIRS;
public function __construct($meta = 0){
parent::__construct(self::DARK_OAK_WOOD_STAIRS, $meta, "Dark Oak Wood Stairs");
$this->meta = $meta;
}
public function getName(){
return "Dark Oak Wood Stairs";
}
public function getDrops(Item $item){

View File

@ -24,21 +24,22 @@ namespace pocketmine\block;
use pocketmine\level\Level;
class DeadBush extends Flowable{
public function __construct(){
parent::__construct(self::DEAD_BUSH, 0, "Dead Bush");
//$this->isReplaceable = true;
$this->hardness = 0;
protected $id = self::DEAD_BUSH;
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getBoundingBox(){
return null;
public function getName(){
return "Dead Bush";
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent === true){ //Replace with common break method
$this->getLevel()->setBlock($this, new Air(), false, false, true);
if($this->getSide(0)->isTransparent() === true){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Diamond extends Solid{
protected $id = self::DIAMOND_BLOCK;
public function __construct(){
parent::__construct(self::DIAMOND_BLOCK, 0, "Diamond Block");
$this->hardness = 30;
}
public function getHardness(){
return 30;
}
public function getName(){
return "Diamond Block";
}
public function getBreakTime(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class DiamondOre extends Solid{
protected $id = self::DIAMOND_ORE;
public function __construct(){
parent::__construct(self::DIAMOND_ORE, 0, "Diamond Ore");
$this->hardness = 15;
}
public function getHardness(){
return 15;
}
public function getName(){
return "Diamond Ore";
}
public function getBreakTime(Item $item){

View File

@ -26,16 +26,24 @@ 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(){
}
public function canBeActivated(){
return true;
}
public function getHardness(){
return 2.5;
}
public function getName(){
return "Dirt";
}
public function onActivate(Item $item, Player $player = null){
if($item->isHoe()){
$item->useOn($this);

View File

@ -30,9 +30,13 @@ use pocketmine\Server;
abstract class Door extends Transparent{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
$this->isSolid = false;
public function canBeActivated(){
return true;
}
public function isSolid(){
return false;
}
private function getFullDamage(){
@ -52,10 +56,7 @@ abstract class Door extends Transparent{
return $first & 0x07 | ($flag ? 8 : 0) | ($flag1 ? 0x10 : 0);
}
public function getBoundingBox(){
if($this->boundingBox !== null){
return $this->boundingBox;
}
protected function recalculateBoundingBox(){
$f = 0.1875;
$damage = $this->getFullDamage();
@ -76,7 +77,7 @@ abstract class Door extends Transparent{
if($j === 0){
if($flag){
if(!$flag1){
$bb = new AxisAlignedBB(
$bb->setBounds(
$this->x,
$this->y,
$this->z,
@ -85,7 +86,7 @@ abstract class Door extends Transparent{
$this->z + $f
);
}else{
$bb = new AxisAlignedBB(
$bb->setBounds(
$this->x,
$this->y,
$this->z + 1 - $f,
@ -95,7 +96,7 @@ abstract class Door extends Transparent{
);
}
}else{
$bb = new AxisAlignedBB(
$bb->setBounds(
$this->x,
$this->y,
$this->z,
@ -107,7 +108,7 @@ abstract class Door extends Transparent{
}elseif($j === 1){
if($flag){
if(!$flag1){
$bb = new AxisAlignedBB(
$bb->setBounds(
$this->x + 1 - $f,
$this->y,
$this->z,
@ -116,7 +117,7 @@ abstract class Door extends Transparent{
$this->z + 1
);
}else{
$bb = new AxisAlignedBB(
$bb->setBounds(
$this->x,
$this->y,
$this->z,
@ -126,7 +127,7 @@ abstract class Door extends Transparent{
);
}
}else{
$bb = new AxisAlignedBB(
$bb->setBounds(
$this->x,
$this->y,
$this->z,
@ -138,7 +139,7 @@ abstract class Door extends Transparent{
}elseif($j === 2){
if($flag){
if(!$flag1){
$bb = new AxisAlignedBB(
$bb->setBounds(
$this->x,
$this->y,
$this->z + 1 - $f,
@ -147,7 +148,7 @@ abstract class Door extends Transparent{
$this->z + 1
);
}else{
$bb = new AxisAlignedBB(
$bb->setBounds(
$this->x,
$this->y,
$this->z,
@ -157,7 +158,7 @@ abstract class Door extends Transparent{
);
}
}else{
$bb = new AxisAlignedBB(
$bb->setBounds(
$this->x + 1 - $f,
$this->y,
$this->z,
@ -169,7 +170,7 @@ abstract class Door extends Transparent{
}elseif($j === 3){
if($flag){
if(!$flag1){
$bb = new AxisAlignedBB(
$bb->setBounds(
$this->x,
$this->y,
$this->z,
@ -178,7 +179,7 @@ abstract class Door extends Transparent{
$this->z + 1
);
}else{
$bb = new AxisAlignedBB(
$bb->setBounds(
$this->x + 1 - $f,
$this->y,
$this->z,
@ -188,7 +189,7 @@ abstract class Door extends Transparent{
);
}
}else{
$bb = new AxisAlignedBB(
$bb->setBounds(
$this->x,
$this->y,
$this->z + 1 - $f,
@ -199,12 +200,12 @@ abstract class Door extends Transparent{
}
}
return $this->boundingBox = $bb;
return $bb;
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->getID() === self::AIR){ //Replace with common break method
if($this->getSide(0)->getId() === self::AIR){ //Replace with common break method
$this->getLevel()->setBlock($this, new Air(), false);
if($this->getSide(1) instanceof Door){
$this->getLevel()->setBlock($this->getSide(1), new Air(), false);
@ -221,7 +222,7 @@ abstract class Door extends Transparent{
if($face === 1){
$blockUp = $this->getSide(1);
$blockDown = $this->getSide(0);
if($blockUp->isReplaceable === false or $blockDown->isTransparent === true){
if($blockUp->canBeReplaced() === false or $blockDown->isTransparent() === true){
return false;
}
$direction = $player instanceof Player ? $player->getDirection() : 0;
@ -234,7 +235,7 @@ abstract class Door extends Transparent{
$next = $this->getSide($face[(($direction + 2) % 4)]);
$next2 = $this->getSide($face[$direction]);
$metaUp = 0x08;
if($next->getID() === $this->id or ($next2->isTransparent === false and $next->isTransparent === true)){ //Door hinge
if($next->getId() === $this->id or ($next2->isTransparent() === false and $next->isTransparent() === true)){ //Door hinge
$metaUp |= 0x01;
}
@ -250,12 +251,12 @@ abstract class Door extends Transparent{
public function onBreak(Item $item){
if(($this->meta & 0x08) === 0x08){
$down = $this->getSide(0);
if($down->getID() === $this->id){
if($down->getId() === $this->id){
$this->getLevel()->setBlock($down, new Air(), true);
}
}else{
$up = $this->getSide(1);
if($up->getID() === $this->id){
if($up->getId() === $this->id){
$this->getLevel()->setBlock($up, new Air(), true);
}
}
@ -267,14 +268,14 @@ abstract class Door extends Transparent{
public function onActivate(Item $item, Player $player = null){
if(($this->meta & 0x08) === 0x08){ //Top
$down = $this->getSide(0);
if($down->getID() === $this->id){
if($down->getId() === $this->id){
$meta = $down->getDamage() ^ 0x04;
$this->getLevel()->setBlock($down, Block::get($this->id, $meta), true);
$players = $this->getLevel()->getUsingChunk($this->x >> 4, $this->z >> 4);
if($player instanceof Player){
unset($players[$player->getID()]);
unset($players[$player->getId()]);
}
$pk = new LevelEventPacket;
$pk = new LevelEventPacket();
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
@ -291,9 +292,9 @@ abstract class Door extends Transparent{
$this->getLevel()->setBlock($this, $this, true);
$players = $this->getLevel()->getUsingChunk($this->x >> 4, $this->z >> 4);
if($player instanceof Player){
unset($players[$player->getID()]);
unset($players[$player->getId()]);
}
$pk = new LevelEventPacket;
$pk = new LevelEventPacket();
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;

View File

@ -0,0 +1,70 @@
<?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;
class DoublePlant extends Flowable{
protected $id = self::DOUBLE_PLANT;
public function __construct($meta = 0){
$this->meta = $meta;
}
public function canBeReplaced(){
return true;
}
public function getName(){
static $names = [
0 => "Sunflower",
1 => "Lilac",
2 => "Double Tallgrass",
3 => "Large Fern",
4 => "Rose Bush",
5 => "Peony"
];
return $names[$this->meta & 0x07];
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent() === true){ //Replace with common break method
$this->getLevel()->setBlock($this, new Air(), false, false, true);
return Level::BLOCK_UPDATE_NORMAL;
}
}
return false;
}
public function getDrops(Item $item){
//TODO
return [];
}
}

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class DoubleSlab extends Solid{
protected $id = self::DOUBLE_SLAB;
public function __construct($meta = 0){
parent::__construct(self::DOUBLE_SLAB, $meta, "Double Slab");
$names = [
$this->meta = $meta;
}
public function getHardness(){
return 30;
}
public function getName(){
static $names = [
0 => "Stone",
1 => "Sandstone",
2 => "Wooden",
@ -36,8 +46,7 @@ class DoubleSlab extends Solid{
6 => "Quartz",
7 => "",
];
$this->name = "Double " . $names[$this->meta & 0x07] . " Slab";
$this->hardness = 30;
return "Double " . $names[$this->meta & 0x07] . " Slab";
}
public function getBreakTime(Item $item){

View File

@ -24,18 +24,29 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class DoubleWoodSlab extends Solid{
protected $id = self::DOUBLE_WOOD_SLAB;
public function __construct($meta = 0){
parent::__construct(self::DOUBLE_WOOD_SLAB, $meta, "Double Wooden Slab");
$names = [
$this->meta = $meta;
}
public function getHardness(){
return 15;
}
public function getName(){
static $names = [
0 => "Oak",
1 => "Spruce",
2 => "Birch",
3 => "Jungle",
4 => "Acacia",
5 => "Dark Oak",
6 => "",
7 => ""
];
$this->name = "Double " . $names[$this->meta & 0x07] . " Wooden Slab";
$this->hardness = 15;
return "Double " . $names[$this->meta & 0x07] . " Wooden Slab";
}
public function getBreakTime(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Emerald extends Solid{
protected $id = self::EMERALD_BLOCK;
public function __construct(){
parent::__construct(self::EMERALD_BLOCK, 0, "Emerald Block");
$this->hardness = 30;
}
public function getHardness(){
return 30;
}
public function getName(){
return "Emerald Block";
}
public function getBreakTime(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class EmeraldOre extends Solid{
protected $id = self::EMERALD_ORE;
public function __construct(){
parent::__construct(self::EMERALD_ORE, 0, "Emerald Ore");
$this->hardness = 15;
}
public function getName(){
return "Emerald Ore";
}
public function getHardness(){
return 15;
}
public function getBreakTime(Item $item){

View File

@ -21,20 +21,36 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
class EndPortal extends Solid{
class EndPortalFrame extends Solid{
protected $id = self::END_PORTAL_FRAME;
public function __construct($meta = 0){
parent::__construct(self::END_PORTAL, $meta, "End Portal");
$this->hardness = 18000000;
$this->meta = $meta;
}
public function getBoundingBox(){
if($this->boundingBox !== null){
return $this->boundingBox;
}
public function getLightLevel(){
return 1;
}
return $this->boundingBox = new AxisAlignedBB(
public function getName(){
return "End Portal Frame";
}
public function getHardness(){
return 18000000;
}
public function isBreakable(Item $item){
return false;
}
protected function recalculateBoundingBox(){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class EndStone extends Solid{
protected $id = self::END_STONE;
public function __construct(){
parent::__construct(self::END_STONE, 0, "End Stone");
$this->hardness = 45;
}
public function getName(){
return "End Stone";
}
public function getHardness(){
return 45;
}
public function getBreakTime(Item $item){

View File

@ -21,7 +21,7 @@
namespace pocketmine\block;
use pocketmine\entity\FallingBlock;
use pocketmine\entity\Entity;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\nbt\tag\Byte;
@ -29,12 +29,11 @@ use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\Double;
use pocketmine\nbt\tag\Enum;
use pocketmine\nbt\tag\Float;
use pocketmine\nbt\tag\Int;
use pocketmine\Player;
abstract class Fallable extends Solid{
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, true);
@ -42,10 +41,10 @@ abstract class Fallable extends Solid{
}
public function onUpdate($type){
if($this->hasPhysics === true and $type === Level::BLOCK_UPDATE_NORMAL){
if($type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(0);
if($down->getID() === self::AIR or ($down instanceof Liquid)){
$fall = new FallingBlock($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new Compound("", [
if($down->getId() === self::AIR or ($down instanceof Liquid)){
$fall = Entity::createEntity("FallingSand", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new Compound("", [
"Pos" => new Enum("Pos", [
new Double("", $this->x + 0.5),
new Double("", $this->y),
@ -60,13 +59,12 @@ abstract class Fallable extends Solid{
new Float("", 0),
new Float("", 0)
]),
"Tile" => new Byte("Tile", $this->getID())
"TileID" => new Int("TileID", $this->getId()),
"Data" => new Byte("Data", $this->getDamage()),
]));
$fall->spawnToAll();
}
return false;
}
}
}

View File

@ -25,17 +25,23 @@ use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
class Farmland extends Solid{
protected $id = self::FARMLAND;
public function __construct($meta = 0){
parent::__construct(self::FARMLAND, $meta, "Farmland");
$this->hardness = 3;
$this->meta = $meta;
}
public function getBoundingBox(){
if($this->boundingBox !== null){
return $this->boundingBox;
}
public function getName(){
return "Farmland";
}
return $this->boundingBox = new AxisAlignedBB(
public function getHardness(){
return 3;
}
protected function recalculateBoundingBox(){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,

View File

@ -21,43 +21,48 @@
namespace pocketmine\block;
use pocketmine\math\AxisAlignedBB;
class Fence extends Transparent{
protected $id = self::FENCE;
public function __construct(){
parent::__construct(self::FENCE, 0, "Fence");
$this->isFullBlock = false;
$this->hardness = 15;
}
public function getBoundingBox(){
if($this->boundingBox !== null){
return $this->boundingBox;
}
public function getHardness(){
return 15;
}
public function getName(){
return "Oak Fence";
}
protected function recalculateBoundingBox(){
$flag = $this->canConnect($this->getSide(2));
$flag1 = $this->canConnect($this->getSide(3));
$flag2 = $this->canConnect($this->getSide(4));
$flag3 = $this->canConnect($this->getSide(5));
$f = $flag2 ? 0 : 0.375;
$f = $flag2 ? 0 : 0.375;
$f1 = $flag3 ? 1 : 0.625;
$f2 = $flag ? 0 : 0.375;
$f3 = $flag1 ? 1 : 0.625;
return $this->boundingBox = new AxisAlignedBB(
return new AxisAlignedBB(
$this->x + $f,
$this->y,
$this->z + $f2,
$this->x + $f1,
$this->y + 1, //TODO: check this, add extra bounding box
$this->y + 1.5,
$this->z + $f3
);
}
public function canConnect(Block $block){
return ($block->getID() !== self::FENCE and $block->getID() !== self::FENCE_GATE) ? $block->isSolid : true;
return (!($block instanceof Fence) and !($block instanceof FenceGate)) ? $block->isSolid() : true;
}
}

View File

@ -0,0 +1,31 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceAcacia extends Fence{
protected $id = self::FENCE_ACACIA;
public function getName(){
return "Acacia Fence";
}
}

View File

@ -0,0 +1,31 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceBirch extends Fence{
protected $id = self::FENCE_BIRCH;
public function getName(){
return "Birch Fence";
}
}

View File

@ -0,0 +1,31 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceDarkOak extends Fence{
protected $id = self::FENCE_DARK_OAK;
public function getName(){
return "Dark Oak Fence";
}
}

View File

@ -26,22 +26,27 @@ use pocketmine\math\AxisAlignedBB;
use pocketmine\Player;
class FenceGate extends Transparent{
protected $id = self::FENCE_GATE;
public function __construct($meta = 0){
parent::__construct(self::FENCE_GATE, $meta, "Fence Gate");
$this->isActivable = true;
if(($this->meta & 0x04) === 0x04){
$this->isFullBlock = true;
}else{
$this->isFullBlock = false;
}
$this->hardness = 15;
$this->meta = $meta;
}
public function getName(){
return "Oak Fence Gate";
}
public function getHardness(){
return 15;
}
public function canBeActivated(){
return true;
}
public function getBoundingBox(){
if($this->boundingBox !== null){
return $this->boundingBox;
}
protected function recalculateBoundingBox(){
if(($this->getDamage() & 0x04) > 0){
return null;
@ -49,21 +54,21 @@ class FenceGate extends Transparent{
$i = ($this->getDamage() & 0x03);
if($i === 2 and $i === 0){
return $this->boundingBox = new AxisAlignedBB(
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z + 0.375,
$this->x + 1,
$this->y + 1,
$this->y + 1.5,
$this->z + 0.625
);
}else{
return $this->boundingBox = new AxisAlignedBB(
return new AxisAlignedBB(
$this->x + 0.375,
$this->y,
$this->z,
$this->x + 0.625,
$this->y + 1,
$this->y + 1.5,
$this->z + 1
);
}
@ -96,11 +101,6 @@ class FenceGate extends Transparent{
3 => 2,
];
$this->meta = ($faces[$player instanceof Player ? $player->getDirection() : 0] & 0x03) | ((~$this->meta) & 0x04);
if(($this->meta & 0x04) === 0x04){
$this->isFullBlock = true;
}else{
$this->isFullBlock = false;
}
$this->getLevel()->setBlock($this, $this, true);
return true;

View File

@ -0,0 +1,32 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceGateAcacia extends FenceGate{
protected $id = self::FENCE_GATE_ACACIA;
public function getName(){
return "Acacia Fence Gate";
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceGateBirch extends FenceGate{
protected $id = self::FENCE_GATE_BIRCH;
public function getName(){
return "Birch Fence Gate";
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceGateDarkOak extends FenceGate{
protected $id = self::FENCE_GATE_DARK_OAK;
public function getName(){
return "Dark Oak Fence Gate";
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceGateJungle extends FenceGate{
protected $id = self::FENCE_GATE_JUNGLE;
public function getName(){
return "Jungle Fence Gate";
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceGateSpruce extends FenceGate{
protected $id = self::FENCE_GATE_SPRUCE;
public function getName(){
return "Spruce Fence Gate";
}
}

View File

@ -0,0 +1,31 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceJungle extends Fence{
protected $id = self::FENCE_JUNGLE;
public function getName(){
return "Jungle Fence";
}
}

View File

@ -0,0 +1,31 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\block;
class FenceSpruce extends Fence{
protected $id = self::FENCE_SPRUCE;
public function getName(){
return "Spruce Fence";
}
}

View File

@ -31,26 +31,35 @@ use pocketmine\Server;
class Fire extends Flowable{
public $hasEntityCollision = true;
protected $id = self::FIRE;
public function __construct($meta = 0){
parent::__construct(self::FIRE, $meta, "Fire");
$this->isReplaceable = true;
$this->breakable = false;
$this->isFullBlock = true;
$this->hardness = 0;
$this->meta = $meta;
}
public function getBoundingBox(){
return null;
public function hasEntityCollision(){
return true;
}
public function getName(){
return "Fire Block";
}
public function getLightLevel(){
return 15;
}
public function isBreakable(Item $item){
return false;
}
public function canBeReplaced(){
return true;
}
public function onEntityCollide(Entity $entity){
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
Server::getInstance()->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$entity->attack($ev->getFinalDamage(), $ev);
}
$entity->attack($ev->getFinalDamage(), $ev);
$ev = new EntityCombustByBlockEvent($this, $entity, 8);
Server::getInstance()->getPluginManager()->callEvent($ev);
@ -67,7 +76,7 @@ class Fire extends Flowable{
if($type === Level::BLOCK_UPDATE_NORMAL){
for($s = 0; $s <= 5; ++$s){
$side = $this->getSide($s);
if($side->getID() !== self::AIR and !($side instanceof Liquid)){
if($side->getId() !== self::AIR and !($side instanceof Liquid)){
return false;
}
}
@ -75,7 +84,7 @@ class Fire extends Flowable{
return Level::BLOCK_UPDATE_NORMAL;
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if($this->getSide(0)->getID() !== self::NETHERRACK){
if($this->getSide(0)->getId() !== self::NETHERRACK){
$this->getLevel()->setBlock($this, new Air(), true);
return Level::BLOCK_UPDATE_NORMAL;

View File

@ -24,8 +24,19 @@ namespace pocketmine\block;
abstract class Flowable extends Transparent{
public $isFlowable = true;
public $isFullBlock = false;
public $isSolid = false;
public function canBeFlowedInto(){
return true;
}
public function isSolid(){
return false;
}
public function getBoundingBox(){
return null;
}
public function getHardness(){
return 0;
}
}

View File

@ -23,10 +23,10 @@ namespace pocketmine\block;
class Furnace extends BurningFurnace{
public function __construct($meta = 0){
parent::__construct($meta);
$this->id = self::FURNACE;
$this->name = "Furnace";
$this->isActivable = true;
protected $id = self::FURNACE;
public function getName(){
return "Furnace";
}
}

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Glass extends Transparent{
protected $id = self::GLASS;
public function __construct(){
parent::__construct(self::GLASS, 0, "Glass");
$this->hardness = 1.5;
}
public function getName(){
return "Glass";
}
public function getHardness(){
return 1.5;
}
public function getDrops(Item $item){

View File

@ -23,8 +23,19 @@ namespace pocketmine\block;
class GlassPane extends Thin{
protected $id = self::GLASS_PANE;
public function __construct(){
parent::__construct(self::GLASS_PANE, 0, "Glass Pane");
}
public function getName(){
return "Glass Pane";
}
public function getHardness(){
return 1.5;
}
}

View File

@ -23,8 +23,19 @@ namespace pocketmine\block;
class GlowingObsidian extends Solid{
protected $id = self::GLOWING_OBSIDIAN;
public function __construct($meta = 0){
parent::__construct(self::GLOWING_OBSIDIAN, $meta, "Glowing Obsidian");
$this->meta = $meta;
}
public function getName(){
return "Glowing Obsidian";
}
public function getLightLevel(){
return 12;
}
}

View File

@ -25,9 +25,23 @@ use pocketmine\item\Item;
use pocketmine\level\Level;
class GlowingRedstoneOre extends Solid{
protected $id = self::GLOWING_REDSTONE_ORE;
public function __construct(){
parent::__construct(self::GLOWING_REDSTONE_ORE, 0, "Glowing Redstone Ore");
$this->hardness = 15;
}
public function getHardness(){
return 15;
}
public function getName(){
return "Glowing Redstone Ore";
}
public function getLightLevel(){
return 9;
}
public function onUpdate($type){

View File

@ -24,9 +24,23 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Glowstone extends Transparent{
protected $id = self::GLOWSTONE_BLOCK;
public function __construct(){
parent::__construct(self::GLOWSTONE_BLOCK, 0, "Glowstone");
$this->hardness = 1.5;
}
public function getName(){
return "Glowstone";
}
public function getHardness(){
return 1.5;
}
public function getLightLevel(){
return 15;
}
public function getDrops(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Gold extends Solid{
protected $id = self::GOLD_BLOCK;
public function __construct(){
parent::__construct(self::GOLD_BLOCK, 0, "Gold Block");
$this->hardness = 30;
}
public function getName(){
return "Gold Block";
}
public function getHardness(){
return 30;
}
public function getBreakTime(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class GoldOre extends Solid{
protected $id = self::GOLD_ORE;
public function __construct(){
parent::__construct(self::GOLD_ORE, 0, "Gold Ore");
$this->hardness = 15;
}
public function getName(){
return "Gold Ore";
}
public function getHardness(){
return 15;
}
public function getBreakTime(Item $item){

View File

@ -25,23 +25,31 @@ use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\item\Item;
use pocketmine\level\generator\object\TallGrass as TallGrassObject;
use pocketmine\level\Level;
use pocketmine\level\Position;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\Server;
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(){
}
public function canBeActivated(){
return true;
}
public function getName(){
return "Grass";
}
public function getHardness(){
return 3;
}
public function getDrops(Item $item){
return [
[Item::DIRT, 0, 1],
@ -54,9 +62,8 @@ class Grass extends Solid{
$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()));
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
if($block->getId() === Block::DIRT){
if($block->getSide(1) instanceof Transparent){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($block, $this, new Grass()));
if(!$ev->isCancelled()){
@ -68,7 +75,7 @@ class Grass extends Solid{
}
public function onActivate(Item $item, Player $player = null){
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){
if($item->getId() === Item::DYE and $item->getDamage() === 0x0F){
$item->count--;
TallGrassObject::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2);

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Gravel extends Fallable{
protected $id = self::GRAVEL;
public function __construct(){
parent::__construct(self::GRAVEL, 0, "Gravel");
$this->hardness = 3;
}
public function getName(){
return "Gravel";
}
public function getHardness(){
return 3;
}
public function getDrops(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class HardenedClay extends Solid{
protected $id = self::HARDENED_CLAY;
public function __construct(){
parent::__construct(self::HARDENED_CLAY, 0, "Hardened Clay");
$this->hardness = 30;
}
public function getName(){
return "Hardened Clay";
}
public function getHardness(){
return 30;
}
public function getBreakTime(Item $item){

View File

@ -25,9 +25,19 @@ use pocketmine\item\Item;
use pocketmine\Player;
class HayBale extends Solid{
protected $id = self::HAY_BALE;
public function __construct($meta = 0){
parent::__construct(self::HAY_BALE, $meta, "Hay Bale");
$this->hardness = 10;
$this->meta = $meta;
}
public function getName(){
return "Hay Bale";
}
public function getHardness(){
return 10;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Ice extends Transparent{
protected $id = self::ICE;
public function __construct(){
parent::__construct(self::ICE, 0, "Ice");
$this->hardness = 2.5;
}
public function getName(){
return "Ice";
}
public function getHardness(){
return 2.5;
}
public function onBreak(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Iron extends Solid{
protected $id = self::IRON_BLOCK;
public function __construct(){
parent::__construct(self::IRON_BLOCK, 0, "Iron Block");
$this->hardness = 30;
}
public function getName(){
return "Iron Block";
}
public function getHardness(){
return 30;
}
public function getBreakTime(Item $item){

View File

@ -23,8 +23,15 @@ namespace pocketmine\block;
class IronBars extends Thin{
protected $id = self::IRON_BARS;
public function __construct(){
parent::__construct(self::IRON_BARS, 0, "Iron Bars");
}
public function getName(){
return "Iron Bars";
}
}

View File

@ -24,10 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class IronDoor extends Door{
protected $id = self::IRON_DOOR_BLOCK;
public function __construct($meta = 0){
parent::__construct(self::IRON_DOOR_BLOCK, $meta, "Iron Door Block");
//$this->isActivable = true;
$this->hardness = 25;
$this->meta = $meta;
}
public function getName(){
return "Iron Door Block";
}
public function getHardness(){
return 25;
}
public function getBreakTime(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class IronOre extends Solid{
protected $id = self::IRON_ORE;
public function __construct(){
parent::__construct(self::IRON_ORE, 0, "Iron Ore");
$this->hardness = 15;
}
public function getName(){
return "Iron Ore";
}
public function getHardness(){
return 15;
}
public function getBreakTime(Item $item){

View File

@ -24,8 +24,15 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class JungleWoodStairs extends Stair{
protected $id = self::JUNGLE_WOOD_STAIRS;
public function __construct($meta = 0){
parent::__construct(self::JUNGLE_WOOD_STAIRS, $meta, "Jungle Wood Stairs");
$this->meta = $meta;
}
public function getName(){
return "Jungle Wood Stairs";
}
public function getDrops(Item $item){

View File

@ -29,13 +29,26 @@ use pocketmine\Player;
class Ladder extends Transparent{
public $hasEntityCollision = true;
protected $id = self::LADDER;
public function __construct($meta = 0){
parent::__construct(self::LADDER, $meta, "Ladder");
$this->isSolid = false;
$this->isFullBlock = false;
$this->hardness = 2;
$this->meta = $meta;
}
public function getName(){
return "Ladder";
}
public function hasEntityCollision(){
return true;
}
public function isSolid(){
return false;
}
public function getHardness(){
return 2;
}
public function onEntityCollide(Entity $entity){
@ -43,15 +56,12 @@ class Ladder extends Transparent{
$entity->onGround = true;
}
public function getBoundingBox(){
if($this->boundingBox !== null){
return $this->boundingBox;
}
protected function recalculateBoundingBox(){
$f = 0.125;
if($this->meta === 2){
return $this->boundingBox = new AxisAlignedBB(
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z + 1 - $f,
@ -60,7 +70,7 @@ class Ladder extends Transparent{
$this->z + 1
);
}elseif($this->meta === 3){
return $this->boundingBox = new AxisAlignedBB(
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
@ -69,7 +79,7 @@ class Ladder extends Transparent{
$this->z + $f
);
}elseif($this->meta === 4){
return $this->boundingBox = new AxisAlignedBB(
return new AxisAlignedBB(
$this->x + 1 - $f,
$this->y,
$this->z,
@ -78,7 +88,7 @@ class Ladder extends Transparent{
$this->z + 1
);
}elseif($this->meta === 5){
return $this->boundingBox = new AxisAlignedBB(
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
@ -93,7 +103,7 @@ class Ladder extends Transparent{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
if($target->isTransparent === false){
if($target->isTransparent() === false){
$faces = [
2 => 2,
3 => 3,
@ -113,7 +123,7 @@ class Ladder extends Transparent{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
/*if($this->getSide(0)->getID() === self::AIR){ //Replace with common break method
/*if($this->getSide(0)->getId() === self::AIR){ //Replace with common break method
Server::getInstance()->api->entity->drop($this, Item::get(LADDER, 0, 1));
$this->getLevel()->setBlock($this, new Air(), true, true, true);
return Level::BLOCK_UPDATE_NORMAL;

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Lapis extends Solid{
protected $id = self::LAPIS_BLOCK;
public function __construct(){
parent::__construct(self::LAPIS_BLOCK, 0, "Lapis Block");
$this->hardness = 15;
}
public function getName(){
return "Lapis Block";
}
public function getHardness(){
return 15;
}
public function getBreakTime(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class LapisOre extends Solid{
protected $id = self::LAPIS_ORE;
public function __construct(){
parent::__construct(self::LAPIS_ORE, 0, "Lapis Ore");
$this->hardness = 15;
}
public function getHardness(){
return 15;
}
public function getName(){
return "Lapis Ore";
}
public function getBreakTime(Item $item){

View File

@ -31,24 +31,38 @@ use pocketmine\Server;
class Lava extends Liquid{
protected $id = self::LAVA;
public function __construct($meta = 0){
parent::__construct(self::LAVA, $meta, "Lava");
$this->hardness = 0;
$this->meta = $meta;
}
public function getLightLevel(){
return 15;
}
public function getName(){
return "Lava";
}
public function getHardness(){
return 0;
}
public function onEntityCollide(Entity $entity){
$entity->fallDistance *= 0.5;
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_LAVA, 4);
Server::getInstance()->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$entity->attack($ev->getFinalDamage(), $ev);
}
$entity->attack($ev->getFinalDamage(), $ev);
$ev = new EntityCombustByBlockEvent($this, $entity, 15);
Server::getInstance()->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$entity->setOnFire($ev->getDuration());
}
if($entity instanceof Player){
$entity->onGround = true;
}
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){

View File

@ -35,16 +35,24 @@ class Leaves extends Transparent{
const ACACIA = 0;
const DARK_OAK = 1;
protected $id = self::LEAVES;
public function __construct($meta = 0){
parent::__construct(self::LEAVES, $meta, "Leaves");
$names = [
$this->meta = $meta;
}
public function getHardness(){
return 1;
}
public function getName(){
static $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;
return $names[$this->meta & 0x03];
}
private function findLog(Block $pos, array $visited, $distance, &$check, $fromSide = null){
@ -53,11 +61,11 @@ class Leaves extends Transparent{
if(isset($visited[$index])){
return false;
}
if($pos->getID() === self::WOOD){
if($pos->getId() === self::WOOD){
return true;
}elseif($pos->getID() === self::LEAVES and $distance < 3){
}elseif($pos->getId() === self::LEAVES and $distance < 3){
$visited[$index] = true;
$down = $pos->getSide(0)->getID();
$down = $pos->getSide(0)->getId();
if($down === Item::WOOD){
return true;
}

View File

@ -29,14 +29,18 @@ use pocketmine\Server;
class Leaves2 extends Leaves{
protected $id = self::LEAVES2;
public function __construct($meta = 0){
Transparent::__construct(self::LEAVES, $meta, "Leaves");
$names = [
$this->meta = $meta;
}
public function getName(){
static $names = [
self::ACACIA => "Acacia Leaves",
self::DARK_OAK => "Dark Oak Leaves",
];
$this->name = $names[$this->meta & 0x03];
$this->hardness = 1;
return $names[$this->meta & 0x01];
}
private function findLog(Block $pos, array $visited, $distance, &$check, $fromSide = null){
@ -45,11 +49,11 @@ class Leaves2 extends Leaves{
if(isset($visited[$index])){
return false;
}
if($pos->getID() === self::WOOD2){
if($pos->getId() === self::WOOD2){
return true;
}elseif($pos->getID() === self::LEAVES2 and $distance < 3){
}elseif($pos->getId() === self::LEAVES2 and $distance < 3){
$visited[$index] = true;
$down = $pos->getSide(0)->getID();
$down = $pos->getSide(0)->getId();
if($down === Item::WOOD2){
return true;
}

View File

@ -28,13 +28,25 @@ use pocketmine\level\Level;
use pocketmine\math\Vector3;
abstract class Liquid extends Transparent{
public $hasEntityCollision = true;
public $isLiquid = true;
public $breakable = false;
public $isReplaceable = true;
public $isSolid = false;
public $isFullBlock = true;
/** @var Vector3 */
private $temporalVector = null;
public function hasEntityCollision(){
return true;
}
public function isBreakable(Item $item){
return false;
}
public function canBeReplaced(){
return true;
}
public function isSolid(){
return false;
}
public $adjacentSources = 0;
public $isOptimalFlowDirection = [0, 0, 0, 0];
@ -54,7 +66,7 @@ abstract class Liquid extends Transparent{
$pos = $this->getLevel()->getBlock($pos);
}
if($pos->getID() !== $this->getID()){
if($pos->getId() !== $this->getId()){
return -1;
}else{
return $pos->getDamage();
@ -66,7 +78,7 @@ abstract class Liquid extends Transparent{
$pos = $this->getLevel()->getBlock($pos);
}
if($pos->getID() !== $this->getID()){
if($pos->getId() !== $this->getId()){
return -1;
}
@ -82,6 +94,10 @@ abstract class Liquid extends Transparent{
public function getFlowVector(){
$vector = new Vector3(0, 0, 0);
if($this->temporalVector === null){
$this->temporalVector = new Vector3(0, 0, 0);
}
$decay = $this->getEffectiveFlowDecay($this);
for($j = 0; $j < 4; ++$j){
@ -99,46 +115,50 @@ abstract class Liquid extends Transparent{
}elseif($j === 3){
++$z;
}
$sideBlock = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
$sideBlock = $this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $z));
$blockDecay = $this->getEffectiveFlowDecay($sideBlock);
if($blockDecay < 0){
if(!$sideBlock->isFlowable){
if(!$sideBlock->canBeFlowedInto()){
continue;
}
$blockDecay = $this->getEffectiveFlowDecay($sideBlock->getSide(0));
$blockDecay = $this->getEffectiveFlowDecay($this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y - 1, $z)));
if($blockDecay >= 0){
$realDecay = $blockDecay - ($decay - 8);
$vector = $vector->add(($sideBlock->x - $this->x) * $realDecay, ($sideBlock->y - $this->y) * $realDecay, ($sideBlock->z - $this->z) * $realDecay);
$vector->x += ($sideBlock->x - $this->x) * $realDecay;
$vector->y += ($sideBlock->y - $this->y) * $realDecay;
$vector->z += ($sideBlock->z - $this->z) * $realDecay;
}
continue;
}else{
$realDecay = $blockDecay - $decay;
$vector = $vector->add(($sideBlock->x - $this->x) * $realDecay, ($sideBlock->y - $this->y) * $realDecay, ($sideBlock->z - $this->z) * $realDecay);
$vector->x += ($sideBlock->x - $this->x) * $realDecay;
$vector->y += ($sideBlock->y - $this->y) * $realDecay;
$vector->z += ($sideBlock->z - $this->z) * $realDecay;
}
}
if($this->getDamage() >= 8){
$falling = false;
if(!$this->getLevel()->getBlock($this->add(0, 0, -1))->isFlowable){
if(!$this->getLevel()->getBlock($this->temporalVector->setComponents($this->x, $this->y, $this->z - 1))->canBeFlowedInto()){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(0, 0, 1))->isFlowable){
}elseif(!$this->getLevel()->getBlock($this->temporalVector->setComponents($this->x, $this->y, $this->z + 1))->canBeFlowedInto()){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(-1, 0, 0))->isFlowable){
}elseif(!$this->getLevel()->getBlock($this->temporalVector->setComponents($this->x - 1, $this->y, $this->z))->canBeFlowedInto()){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(1, 0, 0))->isFlowable){
}elseif(!$this->getLevel()->getBlock($this->temporalVector->setComponents($this->x + 1, $this->y, $this->z))->canBeFlowedInto()){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(0, 1, -1))->isFlowable){
}elseif(!$this->getLevel()->getBlock($this->temporalVector->setComponents($this->x, $this->y + 1, $this->z - 1))->canBeFlowedInto()){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(0, 1, 1))->isFlowable){
}elseif(!$this->getLevel()->getBlock($this->temporalVector->setComponents($this->x, $this->y + 1, $this->z + 1))->canBeFlowedInto()){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(-1, 1, 0))->isFlowable){
}elseif(!$this->getLevel()->getBlock($this->temporalVector->setComponents($this->x - 1, $this->y + 1, $this->z))->canBeFlowedInto()){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(1, 1, 0))->isFlowable){
}elseif(!$this->getLevel()->getBlock($this->temporalVector->setComponents($this->x + 1, $this->y + 1, $this->z))->canBeFlowedInto()){
$falling = true;
}
@ -172,6 +192,10 @@ abstract class Liquid extends Transparent{
$this->checkForHarden();
$this->getLevel()->scheduleUpdate($this, $this->tickRate());
}elseif($type === Level::BLOCK_UPDATE_SCHEDULED){
if($this->temporalVector === null){
$this->temporalVector = new Vector3(0, 0, 0);
}
$decay = $this->getFlowDecay($this);
$multiplier = $this instanceof Lava ? 2 : 1;
@ -180,10 +204,10 @@ abstract class Liquid extends Transparent{
if($decay > 0){
$smallestFlowDecay = -100;
$this->adjacentSources = 0;
$smallestFlowDecay = $this->getSmallestFlowDecay($this->getSide(4), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->getSide(5), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->getSide(2), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->getSide(3), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y, $this->z - 1)), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y, $this->z + 1)), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlock($this->temporalVector->setComponents($this->x - 1, $this->y, $this->z)), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->level->getBlock($this->temporalVector->setComponents($this->x + 1, $this->y, $this->z)), $smallestFlowDecay);
$k = $smallestFlowDecay + $multiplier;
@ -191,7 +215,7 @@ abstract class Liquid extends Transparent{
$k = -1;
}
if(($topFlowDecay = $this->getFlowDecay($this->getSide(1))) >= 0){
if(($topFlowDecay = $this->getFlowDecay($this->level->getBlock($this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y + 1, $this->z))))) >= 0){
if($topFlowDecay >= 8){
$k = $topFlowDecay;
}else{
@ -200,8 +224,8 @@ abstract class Liquid extends Transparent{
}
if($this->adjacentSources >= 2 and $this instanceof Water){
$bottomBlock = $this->getSide(0);
if($bottomBlock->isSolid){
$bottomBlock = $this->level->getBlock($this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y - 1, $this->z)));
if($bottomBlock->isSolid()){
$k = 0;
}elseif($bottomBlock instanceof Water and $bottomBlock->getDamage() === 0){
$k = 0;
@ -216,7 +240,7 @@ abstract class Liquid extends Transparent{
if($k !== $decay){
$decay = $k;
if($decay < 0){
$this->getLevel()->setBlock($this, Block::get(Item::AIR), true);
$this->getLevel()->setBlock($this, new Air(), true);
}else{
$this->getLevel()->setBlock($this, Block::get($this->id, $decay), true);
$this->getLevel()->scheduleUpdate($this, $this->tickRate());
@ -229,9 +253,9 @@ abstract class Liquid extends Transparent{
//$this->updateFlow();
}
$bottomBlock = $this->getSide(0);
$bottomBlock = $this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y - 1, $this->z));
if($bottomBlock->isFlowable or $bottomBlock instanceof Liquid){
if($bottomBlock->canBeFlowedInto() or $bottomBlock instanceof Liquid){
if($this instanceof Lava and $bottomBlock instanceof Water){
$this->getLevel()->setBlock($bottomBlock, Block::get(Item::STONE), true);
return;
@ -244,7 +268,7 @@ abstract class Liquid extends Transparent{
$this->getLevel()->setBlock($bottomBlock, Block::get($this->id, $decay + 8), true);
$this->getLevel()->scheduleUpdate($bottomBlock, $this->tickRate());
}
}elseif($decay >= 0 and ($decay === 0 or !$bottomBlock->isFlowable)){
}elseif($decay >= 0 and ($decay === 0 or !$bottomBlock->canBeFlowedInto())){
$flags = $this->getOptimalFlowDirections();
$l = $decay + $multiplier;
@ -259,19 +283,19 @@ abstract class Liquid extends Transparent{
}
if($flags[0]){
$this->flowIntoBlock($this->getSide(4), $l);
$this->flowIntoBlock($this->level->getBlock($this->temporalVector->setComponents($this->x - 1, $this->y, $this->z)), $l);
}
if($flags[1]){
$this->flowIntoBlock($this->getSide(5), $l);
$this->flowIntoBlock($this->level->getBlock($this->temporalVector->setComponents($this->x + 1, $this->y, $this->z)), $l);
}
if($flags[2]){
$this->flowIntoBlock($this->getSide(2), $l);
$this->flowIntoBlock($this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y, $this->z - 1)), $l);
}
if($flags[3]){
$this->flowIntoBlock($this->getSide(3), $l);
$this->flowIntoBlock($this->level->getBlock($this->temporalVector->setComponents($this->x, $this->y, $this->z + 1)), $l);
}
}
@ -281,8 +305,8 @@ abstract class Liquid extends Transparent{
}
private function flowIntoBlock(Block $block, $newFlowDecay){
if($block->isFlowable){
if($block->getID() > 0){
if($block->canBeFlowedInto()){
if($block->getId() > 0){
$this->getLevel()->useBreakOn($block);
}
@ -314,13 +338,13 @@ abstract class Liquid extends Transparent{
}elseif($j === 3){
++$z;
}
$blockSide = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
$blockSide = $this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $z));
if(!$blockSide->isFlowable and !($blockSide instanceof Liquid)){
if(!$blockSide->canBeFlowedInto() and !($blockSide instanceof Liquid)){
continue;
}elseif($blockSide instanceof Liquid and $blockSide->getDamage() === 0){
continue;
}elseif($blockSide->getSide(0)->isFlowable){
}elseif($this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y - 1, $z))->canBeFlowedInto()){
return $accumulatedCost;
}
@ -340,6 +364,10 @@ abstract class Liquid extends Transparent{
}
private function getOptimalFlowDirections(){
if($this->temporalVector === null){
$this->temporalVector = new Vector3(0, 0, 0);
}
for($j = 0; $j < 4; ++$j){
$this->flowCost[$j] = 1000;
@ -356,13 +384,13 @@ abstract class Liquid extends Transparent{
}elseif($j === 3){
++$z;
}
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
$block = $this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y, $z));
if(!$block->isFlowable and !($block instanceof Liquid)){
if(!$block->canBeFlowedInto() and !($block instanceof Liquid)){
continue;
}elseif($block instanceof Liquid and $block->getDamage() === 0){
continue;
}elseif($block->getSide(0)->isFlowable){
}elseif($this->getLevel()->getBlock($this->temporalVector->setComponents($x, $y - 1, $z))->canBeFlowedInto()){
$this->flowCost[$j] = 0;
}else{
$this->flowCost[$j] = $this->calculateFlowCost($block, 1, $j);

View File

@ -25,9 +25,23 @@ use pocketmine\item\Item;
use pocketmine\Player;
class LitPumpkin extends Solid{
public function __construct(){
parent::__construct(self::LIT_PUMPKIN, "Jack o'Lantern");
$this->hardness = 5;
protected $id = self::LIT_PUMPKIN;
public function getLightLevel(){
return 15;
}
public function getHardness(){
return 5;
}
public function getName(){
return "Jack o'Lantern";
}
public function __construct($meta = 0){
$this->meta = $meta;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Melon extends Transparent{
protected $id = self::MELON_BLOCK;
public function __construct(){
parent::__construct(self::MELON_BLOCK, 0, "Melon Block");
$this->hardness = 5;
}
public function getName(){
return "Melon Block";
}
public function getHardness(){
return 5;
}
public function getDrops(Item $item){

View File

@ -27,13 +27,20 @@ use pocketmine\level\Level;
use pocketmine\Server;
class MelonStem extends Crops{
protected $id = self::MELON_STEM;
public function getName(){
return "Melon Stem";
}
public function __construct($meta = 0){
parent::__construct(self::MELON_STEM, $meta, "Melon Stem");
$this->meta = $meta;
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent === true){
if($this->getSide(0)->isTransparent() === true){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;
}
@ -51,13 +58,13 @@ class MelonStem extends Crops{
}else{
for($side = 2; $side <= 5; ++$side){
$b = $this->getSide($side);
if($b->getID() === self::MELON_BLOCK){
if($b->getId() === self::MELON_BLOCK){
return Level::BLOCK_UPDATE_RANDOM;
}
}
$side = $this->getSide(mt_rand(2, 5));
$d = $side->getSide(0);
if($side->getID() === self::AIR and ($d->getID() === self::FARMLAND or $d->getID() === self::GRASS or $d->getID() === self::DIRT)){
if($side->getId() === self::AIR and ($d->getId() === self::FARMLAND or $d->getId() === self::GRASS or $d->getId() === self::DIRT)){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($side, new Melon()));
if(!$ev->isCancelled()){
$this->getLevel()->setBlock($side, $ev->getNewState(), true);

View File

@ -24,29 +24,39 @@ 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;
protected $id = self::MONSTER_SPAWNER;
public function __construct($meta = 0){
$this->meta = $meta;
}
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 getHardness(){
return 25;
}
public function getDrops(Item $item){
return [];
}
public function getName(){
return "Monster Spawner";
}
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

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class MossStone extends Solid{
protected $id = self::MOSS_STONE;
public function __construct($meta = 0){
parent::__construct(self::MOSS_STONE, $meta, "Moss Stone");
$this->hardness = 30;
$this->meta = $meta;
}
public function getName(){
return "Moss Stone";
}
public function getHardness(){
return 30;
}
public function getBreakTime(Item $item){

View File

@ -24,13 +24,23 @@ namespace pocketmine\block;
use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\level\Position;
use pocketmine\math\Vector3;
use pocketmine\Server;
class Mycelium extends Solid{
protected $id = self::MYCELIUM;
public function __construct(){
parent::__construct(self::MYCELIUM, 0, "Mycelium");
$this->hardness = 2.5;
}
public function getName(){
return "Mycelium";
}
public function getHardness(){
return 2.5;
}
public function getDrops(Item $item){
@ -45,9 +55,8 @@ class Mycelium extends Solid{
$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()));
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
if($block->getId() === Block::DIRT){
if($block->getSide(1) instanceof Transparent){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($block, $this, new Mycelium()));
if(!$ev->isCancelled()){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class NetherBrick extends Solid{
protected $id = self::NETHER_BRICKS;
public function __construct(){
parent::__construct(self::NETHER_BRICKS, 0, "Nether Bricks");
$this->hardness = 30;
}
public function getName(){
return "Nether Bricks";
}
public function getHardness(){
return 30;
}
public function getBreakTime(Item $item){

View File

@ -23,8 +23,15 @@ namespace pocketmine\block;
class NetherBrickStairs extends Stair{
protected $id = self::NETHER_BRICKS_STAIRS;
public function getName(){
return "Nether Bricks Stairs";
}
public function __construct($meta = 0){
parent::__construct(self::NETHER_BRICKS_STAIRS, $meta, "Nether Bricks Stairs");
$this->meta = $meta;
}
}

View File

@ -23,9 +23,19 @@ namespace pocketmine\block;
class NetherReactor extends Solid{
protected $id = self::NETHER_REACTOR;
public function __construct($meta = 0){
parent::__construct(self::NETHER_REACTOR, $meta, "Nether Reactor");
$this->isActivable = true;
$this->meta = $meta;
}
public function getName(){
return "Nether Reactor";
}
public function canBeActivated(){
return true;
}
}

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Netherrack extends Solid{
protected $id = self::NETHERRACK;
public function __construct(){
parent::__construct(self::NETHERRACK, 0, "Netherrack");
$this->hardness = 2;
}
public function getName(){
return "Netherrack";
}
public function getHardness(){
return 2;
}
public function getBreakTime(Item $item){

View File

@ -24,9 +24,19 @@ namespace pocketmine\block;
use pocketmine\item\Item;
class Obsidian extends Solid{
protected $id = self::OBSIDIAN;
public function __construct(){
parent::__construct(self::OBSIDIAN, 0, "Obsidian");
$this->hardness = 6000;
}
public function getName(){
return "Obsidian";
}
public function getHardness(){
return 6000;
}
public function getBreakTime(Item $item){

View File

@ -30,18 +30,28 @@ class Planks extends Solid{
const ACACIA = 4;
const DARK_OAK = 5;
protected $id = self::WOODEN_PLANKS;
public function __construct($meta = 0){
parent::__construct(self::PLANKS, $meta, "Wood Planks");
$names = [
$this->meta = $meta;
}
public function getHardness(){
return 15;
}
public function getName(){
static $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;
return $names[$this->meta & 0x07];
}
}

View File

@ -22,8 +22,18 @@
namespace pocketmine\block;
class Podzol extends Solid{
protected $id = self::PODZOL;
public function __construct(){
parent::__construct(self::PODZOL, 0, "Podzol");
$this->hardness = 2.5;
}
public function getName(){
return "Podzol";
}
public function getHardness(){
return 2.5;
}
}

View File

@ -25,20 +25,22 @@ use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\Player;
class CyanFlower extends Flowable{
public function __construct(){
parent::__construct(self::POPPY, 0, "Cyan Flower");
$this->hardness = 0;
class Poppy extends Flowable{
protected $id = self::POPPY;
public function __construct($meta = 0){
$this->meta = $meta;
}
public function getBoundingBox(){
return null;
public function getName(){
return "Poppy";
}
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){
if($down->getId() === 2 or $down->getId() === 3 or $down->getId() === 60){
$this->getLevel()->setBlock($block, $this, true, true);
return true;
@ -49,7 +51,7 @@ class CyanFlower extends Flowable{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent === true){
if($this->getSide(0)->isTransparent() === true){
$this->getLevel()->useBreakOn($this);
return Level::BLOCK_UPDATE_NORMAL;

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