Compare commits

..

301 Commits

Author SHA1 Message Date
db4bdcd2bd PocketMine-MP Alpha_1.2.1 2013-03-16 13:12:08 +01:00
ce8724c5ed PMF Plugin Loading 2013-03-16 12:52:14 +01:00
d46a61d0c4 Removed Server getting via Plugin Loading 2013-03-16 12:29:29 +01:00
1bfef261ab PMF Plugin Reading 2013-03-16 12:27:23 +01:00
6dfe348767 Added Command Permissions Whitelist 2013-03-16 09:54:42 +01:00
3f10e11ddf Array format fixes 2013-03-16 00:21:50 +01:00
5b79722fa9 Better NACK handling (#133, #16, fixes #75) 2013-03-16 00:16:47 +01:00
fc06e1bcaf Packet Sending Buffering 2013-03-16 00:09:00 +01:00
ffaaca6f2d PMF class 2013-03-15 21:54:19 +01:00
0660409987 Updated Spyc 2013-03-14 21:55:50 +01:00
bbc925b188 Updated Message level of World generation 2013-03-14 21:55:31 +01:00
6f7268902d Added the libtool dependency to the compile script 2013-03-14 19:42:23 +01:00
6851f9c7b1 Added a dynamic title function 2013-03-14 16:36:34 +01:00
9ec9d22bbc BlockAPI::setBlock now uses a Vector3 2013-03-10 13:34:11 +01:00
40842ec794 Fixed Vector3::add() 2013-03-10 13:33:52 +01:00
ab1c28fc57 Changed the api.op.check event check 2013-03-09 22:38:53 +01:00
a9f7d47c25 Added all the future tags 2013-03-09 13:58:22 +01:00
5241f0527b Fix typo for De-Op (I know a very little change) 2013-03-09 22:52:56 +10:30
5c7f397bde Changed default debug level 2013-03-09 12:52:57 +01:00
84ac13d591 Added checks 2013-03-09 12:40:53 +01:00
8bf4b5cafa Added callable type hinting 2013-03-09 10:08:42 +01:00
7acbf13a8a Updated README.md image 2013-03-09 09:33:39 +01:00
fa4813d335 Raised save interval to 25 minutes 2013-03-09 09:31:41 +01:00
3432a69a41 Cancel correctly Handling Events using return true 2013-03-09 09:27:29 +01:00
bc5516867c Fixed Quartz Blocks not getting placed correctly 2013-03-08 23:05:57 +01:00
5c17f77bcc Name update 2013-03-07 19:56:07 +01:00
5fab555c48 Real Minecraft username check 2013-03-07 18:46:04 +01:00
ba3dfd91db Removed unnecesary replace 2013-03-07 18:11:35 +01:00
8f21eb41ee Added message separation 2013-03-07 18:06:51 +01:00
d90e41c0d5 Fixed Server description not being displayed 2013-03-07 18:05:33 +01:00
aecfbbbdc1 Removed flying damage 2013-03-07 17:56:33 +01:00
1c63448c6c Drop in the correct position 2013-03-07 17:44:28 +01:00
8253d63d9b Case-insensitive playernames, removed Client ID kick 2013-03-07 17:43:44 +01:00
a7d8e22e7e Player inventory is changed using chests (Fixes #127) 2013-03-07 17:36:19 +01:00
ad11851c61 Remove items from Player inventory on drop 2013-03-07 17:15:12 +01:00
b259ed2532 Fixed #124 2013-03-06 20:29:49 +01:00
9510cbd716 New block touch event 2013-03-06 20:17:38 +01:00
8a345e6582 Target player gets notified of op 2013-03-06 19:28:24 +01:00
66fe5d2a3e Added Kicking on Ban 2013-03-06 19:21:50 +01:00
7f88ab95e2 Added the /sudo command 2013-03-06 19:19:12 +01:00
3355f71ab3 Added a tile.update event to the container slot change 2013-03-06 19:00:48 +01:00
e8c2662258 Get Item Lists from BlockAPI::fromString() method 2013-03-06 16:43:25 +01:00
6c4900cd32 Dev version 2013-03-06 14:40:58 +01:00
265549906b Version 2013-03-06 14:38:24 +01:00
b1003500c6 Revert "Possible Solution to Issue #119"
This reverts commit 365b7bec7d.
2013-03-06 14:37:45 +01:00
804636b99f Revert "Updated Possible Fix to #119"
This reverts commit 139dfdf59f.
2013-03-06 14:37:40 +01:00
139dfdf59f Updated Possible Fix to #119 2013-03-06 20:25:48 +10:30
a85c865099 OpCheck Typo fixes #121 2013-03-06 19:06:24 +10:30
365b7bec7d Possible Solution to Issue #119 2013-03-06 18:29:59 +10:30
b0722a8ab1 Changed to next release Alpha_1.3dev 2013-03-05 20:44:34 +01:00
69de47da92 PocketMine-MP Alpha_1.2 release 2013-03-05 20:36:24 +01:00
f4ce715efc Furnace Simplification 2013-03-05 20:23:39 +01:00
55cb79fdf6 Send Slot Data to other players opened chests 2013-03-05 20:17:22 +01:00
4db8c0e68d Functional Chests 2013-03-05 20:09:53 +01:00
68d71b367d Force drops on Creative mode 2013-03-05 18:00:54 +01:00
7e8e273be7 Mob Drops 2013-03-05 17:54:34 +01:00
7cf9c03735 Better Entity attacking system 2013-03-05 17:37:09 +01:00
52aa57d400 Less BlockAPI::cancelAction lag, send only to the starter Player 2013-03-05 17:19:18 +01:00
845e48db66 Instant Break protection 2013-03-05 17:16:26 +01:00
0ab5fc8fcd Entity::getDirection() method 2013-03-05 17:03:34 +01:00
3b2a7e68f3 Fixed DevTools plugin related issues 2013-03-05 13:26:10 +01:00
8c32b3d896 Removed the last backtrace funcion due to an infinite loop 2013-03-05 12:51:39 +01:00
a3e141672a Added option to change the DATA_PATH via CLI argument data-path=<directory> 2013-03-05 12:43:35 +01:00
c60e15a682 Correct Line Breaks 2013-03-04 21:36:07 +01:00
76fcad92b3 Pretty print options for Config JSON 2013-03-04 17:29:15 +01:00
a964c0e3ec Added Stack Count 2013-03-04 17:01:28 +01:00
474c1d2093 Added Vector3 preload 2013-03-04 17:01:15 +01:00
354893ba11 BlockAPI::getBlockFace() method optimization to use the Vector3 method 2013-03-04 16:50:41 +01:00
287fa7e551 Updated the BlockAPI::drop method 2013-03-04 16:50:11 +01:00
326864f889 Fixed FILE_PATH on tests 2013-03-02 15:35:07 +01:00
3e1dfa07c0 Once again on PHP 5.4.12, fixed krakjoe/pthreads#62 2013-03-01 18:48:44 +01:00
5aa34b2803 Downgrade to PHP 5.4.11 as a temp. fix to krakjoe/pthreads#62 2013-03-01 15:38:20 +01:00
ccd1231d42 Remove Chest TileEntities on break 2013-02-27 19:32:59 +01:00
69a1c97a36 Updated PHP to 5.4.12 2013-02-26 19:54:50 +01:00
28bfdbb3c5 Fixed the String test (fixes #117) 2013-02-26 19:21:13 +01:00
0852c42de7 Removing sudo on travis 2013-02-26 12:18:05 +01:00
44dc1b13e3 Fixed breaking a bed from the bottom part 2013-02-25 20:54:16 +01:00
8d522077c4 Removed big & nasty unhandled message for inventory sending 2013-02-25 20:51:32 +01:00
53b79a1f7b Fixed Bed Breaking & added return info 2013-02-25 20:49:34 +01:00
66d43228cd Added comments to bed block fix 2013-02-19 18:10:55 +10:30
536bfa1f46 Correct Bed Breaking UNSTABLE NEEDS TESTING 2013-02-19 17:43:20 +10:30
6bed89f4b5 Update PocketMine-MP.php 2013-02-16 23:12:38 +01:00
20e6d19d85 Added GMP base 2013-02-15 20:11:40 +01:00
b3db08a370 Removed Math_BigInteger dependency 2013-02-15 20:04:21 +01:00
39df588dd9 Removed header 2013-02-14 21:24:26 +01:00
874571d572 Changes made to be compatible with the DevTools plugin 2013-02-14 20:37:16 +01:00
717c668787 Removed includes, moving to only one main folder 2013-02-13 20:35:56 +01:00
09e81b8e17 New tests branch 2013-02-12 16:55:01 +01:00
45192c4448 Updated gamemode constant names 2013-02-12 16:42:58 +01:00
6c4670421c Moved tests 2013-02-12 16:34:52 +01:00
eff4631f35 Fixes #103 2013-02-11 21:04:35 +01:00
20066ddb89 Added GeneralConstants file 2013-02-11 20:29:37 +01:00
ed1f5f225e Fixed glowstone block placing 2013-02-11 20:25:18 +01:00
881e363d1b Readme 2013-02-11 19:44:53 +01:00
db8e00ca4c Update README.md 2013-02-10 16:59:23 +01:00
ce925cd382 Updated ConsoleAPI::alias(), BlockAPI::fromString() 2013-02-10 11:04:14 +01:00
fbc1873e06 Merge branch 'master' of https://github.com/shoghicp/PocketMine-MP 2013-02-10 19:42:59 +10:30
1a2fbd7389 Added Iron Tool IDs 2013-02-10 19:41:58 +10:30
5970927e8a Fixed teleport commands for disconnected players 2013-02-09 21:03:54 +01:00
7c33c4f75a Set a name for unnamed worlds 2013-02-09 20:39:52 +01:00
6dcf9e5da1 Preparation for future changes 2013-02-09 18:07:25 +01:00
4e4aab247a Fixed #93 Path with spaces bug 2013-02-09 13:06:40 +01:00
6ef89cbf8c Added Build status 2013-02-09 12:28:52 +01:00
88b7cb7228 Merge branch 'master' of https://github.com/shoghicp/PocketMine-MP 2013-02-09 21:37:13 +10:30
731827cf7d Added Ingot Item IDs 2013-02-09 21:35:50 +10:30
9281d68bea Exit after an error with exit(1) 2013-02-09 11:32:53 +01:00
1cc15ddd42 Updated README.md 2013-02-09 11:27:17 +01:00
d0057b6595 Merge branch 'master' of https://github.com/shoghicp/PocketMine-MP 2013-02-09 20:44:00 +10:30
c7866fc352 Removed Old and Added New mailing list to README 2013-02-09 20:43:02 +10:30
862938cfc7 Fixed /whitelist reload crash 2013-02-09 10:41:36 +01:00
afbc3da6ed Now following PHPUnit file name pattern 2013-02-09 01:06:36 +01:00
aaaa68ff66 Fixed YAML syntax error 2013-02-09 01:01:20 +01:00
c46eee611f Added some Travis-CI tests 2013-02-09 00:57:41 +01:00
90c8ac1461 Better Console Alias 2013-02-08 17:46:05 +01:00
967a929723 Send Inventory Support 2013-02-08 14:17:52 +01:00
506b9f4a4f Updated packet names 2013-02-08 13:58:00 +01:00
539993751f Moved chat message to console 2013-02-08 13:52:37 +01:00
32df30448b Typo 2013-02-07 17:10:02 +01:00
e7d56a837f Added __toString() to Player, Block and Item classes & added protocol order enforcement after login 2013-02-07 17:04:04 +01:00
4d05d7da0d Fixed #96 server crash 2013-02-07 16:56:10 +01:00
498c050da7 Added OPs and permission checks 2013-02-07 09:37:15 +01:00
c2e55941d8 Added player commands, better console API and implemented future player chat 2013-02-07 09:24:44 +01:00
72388fa3cb Corrected Feather and Added Brick 2013-02-07 16:24:06 +10:30
318590e664 Merge branch 'master' of https://github.com/shoghicp/PocketMine-MP 2013-02-07 16:12:24 +10:30
466ae6290d Merge pull request #95 from snake302/patch-2
Update compile_php.sh
2013-02-06 13:14:06 -08:00
816ef08ad2 Update compile_php.sh
Update version
- pthread
- curl 7.29.0
2013-02-07 00:26:44 +04:00
e288a8a880 Multiple Paintings 2013-02-06 17:04:19 +01:00
d2dcf4f43a Switched gamemode handler to Player object 2013-02-06 16:18:15 +01:00
4aa0f8f8d1 Slab placement fix 2013-02-06 16:06:23 +01:00
5bca4242c2 Bedrock breakeable 2013-02-06 15:59:51 +01:00
93fa008acb Correct Painting placement 2013-02-06 15:57:48 +01:00
639cfc8ab8 GMP version 2013-02-06 11:22:55 +01:00
854599005a Fixed assembly instructions blocking compilation on iOS 2013-02-06 11:18:23 +01:00
72bc35a219 changes 2013-02-06 10:44:04 +01:00
d76408b809 Added Feather Item Code 2013-02-06 20:05:14 +10:30
320dc1af88 Working on Item IDs Added COAL APPLE DIAMOND STICK BOWL 2013-02-06 19:57:32 +10:30
1c05455514 Weird Painting spawn (WiP) 2013-02-05 23:25:40 +01:00
0be3379720 Updated view-distance 2013-02-05 21:43:01 +01:00
e433f0f6dc Flying damage 2013-02-05 21:33:30 +01:00
f53e08bb84 Glass pane suffocation 2013-02-05 21:18:27 +01:00
09dd47722b Meaningful crash reports 2013-02-05 19:15:51 +01:00
74f139ea85 Fixed server crash 2013-02-05 17:58:46 +01:00
b0c520f72a Send only field of view + Chunk resend support 2013-02-05 17:53:22 +01:00
e5ed7e04cf Send MiniChunks 2013-02-05 17:36:38 +01:00
7f92c6fab3 Automatic channel selection & use PocketMine.org API 2013-02-05 16:44:13 +01:00
50815c7ca8 Fixed #92 crash 2013-02-05 07:25:15 +01:00
67925b7df2 Snow Layer is now replaceable and flowable 2013-02-04 23:29:01 +01:00
23dc1033d5 Better chunk distance calculation 2013-02-04 23:11:45 +01:00
34f0e5170b Better door Hinges 2013-02-04 23:03:41 +01:00
e07302b021 Improvement in chunk sending to reduce server lag 2013-02-04 22:48:06 +01:00
ac6c3c7e69 Allow binding to an specific IP 2013-02-04 22:37:56 +01:00
6839001dc3 New Chunks are sent based on the current player position 2013-02-04 22:17:23 +01:00
1b37caf732 Added fast Item check 2013-02-04 20:48:02 +01:00
a07e002565 Added tile update event 2013-02-04 20:31:02 +01:00
25549bbf51 Updated GMP version 2013-02-04 20:27:45 +01:00
6b77a69302 Updated API methods to use less events 2013-02-04 20:27:36 +01:00
565cb9781c Bed placement 2013-02-04 19:57:23 +01:00
719dff6e3c Added API Version check 2013-02-04 19:39:00 +01:00
4f0517a5a7 Added Sign placement 2013-02-04 19:35:11 +01:00
3e87d1927d Cactus Placement 2013-02-04 19:08:31 +01:00
7e7f1892fd Instant growth using bonemeal 2013-02-04 19:00:21 +01:00
fee04cd0d9 Tilling Dirt & Grass, tall gras growth 2013-02-04 18:54:48 +01:00
a718294a08 Seed placement 2013-02-04 18:41:23 +01:00
65280d85d1 Spawning blocks/items using its name 2013-02-04 17:44:41 +01:00
cdb05f0695 Updated Entity class to reflect changes in BlockAPI 2013-02-04 17:26:55 +01:00
37f5626e9a Added more future possible placements for 2013-02-04 17:21:11 +01:00
bb27c0623c Made liquid blocks replaceable 2013-02-04 17:16:01 +01:00
3519cb230c Correct Sugarcane placement 2013-02-04 17:15:01 +01:00
213cda27aa Added conversion between Items <==> Blocks 2013-02-04 16:26:47 +01:00
d5aa898ffe Finished Adding Item IDs 2013-02-04 16:13:11 +01:00
f1c593d809 Fix for crashes via item (MCPE-1198) 2013-02-04 15:02:21 +01:00
3578b90a39 Ladder placement 2013-02-03 22:53:22 +01:00
afe33202dc Added Chest & Furnace placement 2013-02-03 22:50:59 +01:00
a5651c0f43 Door Placement, Breaking and Activation 2013-02-03 22:39:30 +01:00
9cdd616852 Corrected Fence Gate activation 2013-02-03 21:21:16 +01:00
084acfab00 Fence Gate Placement 2013-02-03 21:17:55 +01:00
59ae4f6faa Trapdoor placement & activation 2013-02-03 21:13:16 +01:00
e15392f7bc Added Quartz Stairs to placement 2013-02-03 21:03:20 +01:00
a3260814b8 Upside-down stairs placement 2013-02-03 21:01:21 +01:00
8df59078ad Stair Block placement 2013-02-03 20:59:34 +01:00
b45676d2b5 Fixed Torch block target 2013-02-03 20:47:58 +01:00
399050fc4e Added Torches placement 2013-02-03 20:45:12 +01:00
3ecbe7dbf7 Added Mushroom placement 2013-02-03 20:24:22 +01:00
a9c7a6642e Added flowers placement 2013-02-03 20:23:07 +01:00
d1610ce7a1 Check for player in range for slab placement 2013-02-03 20:21:03 +01:00
fb9a0f2119 Slab placement 2013-02-03 20:15:55 +01:00
d9c87161ba Place/Breaking/Activation logic separated from BlockAPI 2013-02-03 18:55:59 +01:00
6156baab85 Added Liquid check to Fall Damage 2013-02-03 11:03:54 +01:00
bf63065d4e Added Fall damage message 2013-02-03 10:55:54 +01:00
38a1f82456 Added Fall Damage 2013-02-03 10:51:12 +01:00
861a017fa0 Fixed redstone IDs 2013-02-02 21:14:49 +01:00
c95f671271 Added block classes to BlockAPI 2013-02-02 21:12:56 +01:00
49faebde2c Added all the blocks 2013-02-02 21:06:26 +01:00
bb68f8f305 Added PHP version check 2013-02-02 20:27:07 +01:00
8513a34358 Added construct method 2013-02-02 19:52:06 +01:00
8a9762cd31 Second sugarcane fix 2013-02-02 19:03:45 +01:00
38f40eb540 Fix for growing trees 2013-02-02 18:55:53 +01:00
69d2557e32 Fix for sugarcane placing 2013-02-02 18:50:54 +01:00
8d6d5306c1 Added Liquids properties 2013-02-02 17:50:17 +01:00
328cc968bd Added more block properties 2013-02-02 17:38:15 +01:00
e6c2ddbb47 Fixed usage stats 2013-02-02 16:21:00 +01:00
ad98fbf380 Added block info to /give command 2013-02-02 16:19:31 +01:00
34db027ffd Corrected block metadata 2013-02-02 15:53:22 +01:00
bbd113692e Disallow placing torches on ceilings 2013-02-02 15:43:20 +01:00
888e84dd69 Block Names 2013-02-02 15:42:06 +01:00
5a054a8ab4 Added new methods of Block properties (WiP) 2013-02-02 13:36:18 +01:00
4c06b384c7 Added Block Properties 2013-02-02 12:50:53 +01:00
4e740e1862 Next dev version 2013-02-01 18:30:22 +01:00
c9e459cb0f Stable release Alpha_1.1.1 2013-02-01 18:28:25 +01:00
d24d826ffd Adventure Mode 2013-02-01 18:15:14 +01:00
eaa3006d51 Implemented nametags 2013-02-01 15:02:36 +01:00
198a0e69de Updated target version 2013-02-01 00:18:35 +01:00
c7e1a36bd5 Updated version to next development release 2013-01-31 18:28:29 +01:00
f0aecabef7 Updated Version 2013-01-31 18:20:31 +01:00
60c57a6330 Correct and new slab placement (upside-down) 2013-01-31 18:20:01 +01:00
ba4fe61cdb Better event handling 2013-01-31 17:23:50 +01:00
a485536716 Fixed protocol errors 2013-01-30 23:38:07 +01:00
9ef2dc6fe1 Small changes, Ellie 2013-01-30 20:49:34 +01:00
d0a08d16e7 Added new packets 2013-01-30 20:21:18 +01:00
0e889b0139 Armor is shown on multiplayer 2013-01-30 19:57:11 +01:00
fe8b4b7aa7 Added Armor 2013-01-30 18:46:06 +01:00
1e8b012a6e Added structure version 2013-01-30 18:09:19 +01:00
5096cdcde8 Added item pickup delay 2013-01-30 18:02:13 +01:00
08b67428a0 Placing signs text 2013-01-30 17:07:43 +01:00
b697f1441e Protocol changes 4 2013-01-30 16:29:00 +01:00
62578d5fc7 Protocol changes 3 2013-01-30 16:25:26 +01:00
c787142346 Protocol changes 2 2013-01-30 16:13:33 +01:00
db38b824b7 Protocol changes 1 2013-01-30 16:00:22 +01:00
a75f8c2737 Updating version & protocol enforcement 2013-01-30 15:35:33 +01:00
9a8850cb9c Added Stonecutter 2013-01-30 12:47:47 +01:00
8d232cf623 Save paintings 2013-01-29 22:44:19 +01:00
a7079fc49b Correctly handle paintings 2013-01-29 22:38:48 +01:00
71b12191b2 Eating 2013-01-29 20:53:43 +01:00
2011d1d339 Void damage 2013-01-29 20:01:33 +01:00
1976e1c6f6 Item movement fix 2013-01-29 19:29:16 +01:00
5a2156c2bf New compile options for speed improvement 2013-01-29 19:05:47 +01:00
a86213dad8 Include Yaw and Pitch in entity tracking 2013-01-29 17:16:20 +01:00
6095432a4f Updated versions 2013-01-29 10:01:46 +01:00
46f7279a26 Fixes #83 #82 2013-01-29 08:40:36 +01:00
da2b800ea8 Changes in item spawning 2013-01-28 23:07:17 +01:00
862947ab6b Entity Motion packet (WiP) 2013-01-28 22:48:18 +01:00
f8179f0f7c Removed var_dump()! 2013-01-28 20:30:31 +01:00
db9625b52f Entity Gravity 2013-01-28 20:26:57 +01:00
fe3be181e8 Sign placing improvement 2013-01-28 19:06:39 +01:00
8a5708f47a Placing Signs 2013-01-28 19:01:41 +01:00
df46e241d3 Added marble block 2013-01-28 18:37:26 +01:00
104817162d Added upside-down stairs 2013-01-28 18:19:16 +01:00
50ae0953ac Allow for command-line arguments to starter scripts 2013-01-28 18:10:43 +01:00
d9e9b9fd22 Updated target version 2013-01-28 16:22:11 +01:00
eeb623cf21 Added new 0.6.0 blocks 2013-01-28 16:21:50 +01:00
1474d8c785 Better Tile selection & player death check and fix 2013-01-27 23:21:08 +01:00
26fb652c5a Added entity dead check for damage 2013-01-27 23:08:30 +01:00
c06ffe3003 TileEntity spawning improvement 2013-01-27 22:58:54 +01:00
2cb7a21b76 Entity and TileEntity saving 2013-01-27 21:33:57 +01:00
5c11f48270 Tile Entities & Signs 2013-01-27 19:36:12 +01:00
3c4888521d Fix for feet suffocation 2013-01-27 19:14:51 +01:00
d54161f5ca Fixed Signs sufocation 2013-01-27 18:46:09 +01:00
67341c6420 Added regeneration fix, item despawn and damage check 2013-01-27 18:23:51 +01:00
2eb93c1676 Entity metadata 2013-01-27 13:32:55 +01:00
d69291e2fa Added logged in checks 2013-01-27 11:34:24 +01:00
0c5826c8ab Water now generates source blocks 2013-01-27 11:29:43 +01:00
880121a83f Fixed a special water & lava case 2013-01-27 00:29:25 +01:00
0082bc9d10 Lava & water flow now creates stone, cobblestona and obsidian 2013-01-27 00:10:34 +01:00
895e001216 Fixed PHP-Powered memory leaks 2013-01-26 22:00:34 +01:00
1f8939da6e Fixed entities memory leak 2013-01-26 21:45:31 +01:00
c77a3c2f87 Added new IP site 2013-01-26 20:57:13 +01:00
f476cf6943 Send optional usage data 2013-01-26 20:50:34 +01:00
8e3efa0b7e Removed unknown Packet 0xa9 2013-01-26 19:01:05 +01:00
81423e6c3d Fixed health not being correctly displayed after reconnect 2013-01-26 18:55:09 +01:00
e1cf3cc25e Entity death status 2013-01-26 18:51:50 +01:00
fe7138b21e Entity moving optimization 2013-01-26 18:44:13 +01:00
234aee9dfa Entity harm sound 2013-01-26 18:24:10 +01:00
88725100a0 Version - Arggghhhhh!!!! 2013-01-26 17:36:34 +01:00
15772bfad4 Version 2013-01-26 17:34:02 +01:00
afbb5fab04 Fixed old & deprecated plugins not being able to create a config file 2013-01-26 17:32:56 +01:00
00c3201580 Fixed suffocating in fences 2013-01-26 17:24:05 +01:00
36fdb10b9e Fixed random suffocation 2013-01-26 17:19:52 +01:00
828b794555 Fixed suffocating in doors 2013-01-26 17:09:00 +01:00
e1ce88c0ef Fixed creative mode damage 2013-01-26 17:06:30 +01:00
4b744d7af3 Fixed server crash releated to inventory spawning 2013-01-26 16:58:10 +01:00
59a95aadd2 Fixed server crash 2013-01-26 16:23:33 +01:00
20035d18cd Updated version 2013-01-26 14:50:20 +01:00
0425b630ca Updated homepage 2013-01-26 14:38:41 +01:00
d3c6c41ad0 Removed irrelevant things 2013-01-26 14:36:39 +01:00
0ae467c33f Bonemeal tall grass and flowers grow 2013-01-26 14:27:56 +01:00
f917111f31 Implemented drowing damage 2013-01-26 13:44:38 +01:00
ac0fab8f0b Made Zlib required 2013-01-26 13:21:58 +01:00
d1d720e9ef Updated compiler to use less instructions & disk usage 2013-01-26 13:15:53 +01:00
2a63699dcc Updated Entity::touchingBlock() 2013-01-26 12:59:22 +01:00
6a0b3c0e9a Kill messages 2013-01-26 12:56:29 +01:00
09385daf60 Better damage handling + cactus damage 2013-01-26 12:53:37 +01:00
061faaa410 Entity closing fix 2013-01-26 12:31:09 +01:00
26da585889 health regeneration cancelled when dead 2013-01-26 12:12:59 +01:00
a0cb4d2698 Fixed item restoration duplication 2013-01-26 11:57:19 +01:00
5101391c29 Lava, fire and suffocation damage 2013-01-26 11:31:38 +01:00
f06f1d81c1 Fixed cURL version 2013-01-25 14:24:00 +01:00
75eb324967 Added inline compiler optimization for big servers 2013-01-24 17:11:30 +01:00
e5bed548b9 Added Kick API 2013-01-24 19:13:48 +10:30
fde7b5ab5d New compiler using variables to handle versions 2013-01-23 22:16:24 +01:00
237ad4eee4 Fixed random entity memory leak + loops 2013-01-23 20:50:01 +01:00
6660a0a771 Changed version to development 2013-01-23 20:20:12 +01:00
185 changed files with 9271 additions and 6120 deletions

2
.gitignore vendored
View File

@ -3,10 +3,12 @@ worlds/*
plugins/*
logs/*
*.log
*.pmf
server.properties
white-list.txt
banned-ips.txt
banned.txt
ops.txt
#################
## Eclipse

19
.travis.yml Normal file
View File

@ -0,0 +1,19 @@
language: php
php:
- 5.4
before_script:
- pecl install channel://pecl.php.net/pthreads-0.0.42
- git clone --depth=100 --quiet --branch=tests git://github.com/shoghicp/PocketMine-MP.git $(pwd)/tests/
script:
- phpunit tests/
notifications:
email: false
irc:
channels:
- "irc.freenode.org#mcpedevs"
template:
- "PocketMine-MP #%{build_number} %{commit}: %{message} (%{build_url})"

View File

@ -25,11 +25,15 @@ the Free Software Foundation, either version 3 of the License, or
*/
require_once(dirname(__FILE__)."/src/common/dependencies.php");
require_once("API/ServerAPI.php");
/***REM_START***/
require_once(dirname(__FILE__)."/src/config.php");
require_once(FILE_PATH."/src/functions.php");
require_once(FILE_PATH."/src/dependencies.php");
/***REM_END***/
$server = new ServerAPI();
$server->run();//$server->start();
//$server->join();
$server->run();
kill(getmypid()); //Fix for segfault
kill(getmypid()); //Fix for segfault

View File

@ -1,6 +1,6 @@
![](http://shoghicp.github.com/PocketMine-MP/favicon.png)
# PocketMine-MP
# PocketMine-MP [![Build Status](https://travis-ci.org/shoghicp/PocketMine-MP.png?branch=master)](https://travis-ci.org/shoghicp/PocketMine-MP)
```
This program is free software: you can redistribute it and/or modify
@ -17,31 +17,29 @@ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
```
__PocketMine-MP is a Server for Minecraft Pocket Edition done in PHP__. It has a Plugin API that enables a developer to extend it and add new features, or change default ones.
__PocketMine-MP is a Server for Minecraft Pocket Edition__. It has a Plugin API that enables a developer to extend it and add new features, or change default ones.
The entire server is done in PHP, and has been tested, profiled and optimized to run smoothly.
### [Homepage](http://shoghicp.github.com/PocketMine-MP/)
### [Go to Wiki for more information](https://github.com/shoghicp/PocketMine-MP/wiki)
### [Homepage](http://www.pocketmine.org/)
### [FAQ: Frequently Asked Questions](https://github.com/shoghicp/PocketMine-MP/wiki/Frequently-Asked-Questions)
### [@PocketMine](https://twitter.com/PocketMine)
### [Help Page](http://www.pocketmine.org/help.php)
### [Mailing List](https://groups.google.com/forum/#!forum/pocketmine-development) pocketmine-development@googlegroups.com
### [Twitter @PocketMine](https://twitter.com/PocketMine)
## IRC #mcpedevs @ irc.freenode.net
* [WebIRC](http://webchat.freenode.net?channels=mcpedevs&uio=d4)
## Third-party Libraries Used
* __[PHP cURL](http://php.net/manual/en/book.curl.php)__
* __[PHP Sockets](http://php.net/manual/en/book.sockets.php)__
* __[PHP SQLite3](http://php.net/manual/en/book.sqlite3.php)__
* __[cURL](http://curl.haxx.se/)__: cURL is a command line tool for transferring data with URL syntax
* __[GMP](http://gmplib.org/)__: Arithmetic without limitations
* __[Zlib](http://www.zlib.net/)__: A Massively Spiffy Yet Delicately Unobtrusive Compression Library
* __[PHP pthreads](https://github.com/krakjoe/pthreads)__ by _[krakjoe](https://github.com/krakjoe)_: Threading for PHP - Share Nothing, Do Everything.
* __[PHP NBT](https://github.com/TheFrozenFire/PHP-NBT-Decoder-Encoder/blob/master/nbt.class.php)__ by _[TheFrozenFire](https://github.com/TheFrozenFire)_: Class for reading in NBT-format files (modified to handle Little-Endian files).
* __[Math_BigInteger](http://phpseclib.sourceforge.net/math/intro.html)__ by _[phpseclib](http://phpseclib.sourceforge.net/)_: Pure-PHP arbitrary precission integer arithmetic library
* __[Spyc](https://github.com/mustangostang/spyc/blob/master/Spyc.php)__ by _[Vlad Andersen](https://github.com/mustangostang)_: A simple YAML loader/dumper class for PHP.
* __[ANSICON](https://github.com/adoxa/ansicon)__ by _[Jason Hood](https://github.com/adoxa)_: Process ANSI escape sequences for Windows console programs.
## IRC #mcpedevs @ irc.freenode.net
* [WebIRC](http://webchat.freenode.net?channels=mcpedevs&uio=d4)

View File

@ -1,128 +1,146 @@
#!/bin/bash
echo "[PocketMine] PHP installer and compiler for Linux - by @shoghicp v0.3"
COMPILER_VERSION="0.9"
PHP_VERSION="5.4.12"
ZEND_VM="GOTO"
ZLIB_VERSION="1.2.7"
GMP_VERSION="5.1.1"
PTHREADS_VERSION="fc8622882bed09aa181b3eb1cb33c046ce11199b"
CURL_VERSION="curl-7_29_0"
#READLINE_VERSION="6.2"
echo "[PocketMine] PHP installer and compiler for Linux & Mac - by @shoghicp v$COMPILER_VERSION"
DIR=`pwd`
date > $DIR/install.log 2>&1
uname -a >> $DIR/install.log 2>&1
date > "$DIR/install.log" 2>&1
uname -a >> "$DIR/install.log" 2>&1
echo "[INFO] Checking dependecies"
type make >> $DIR/install.log 2>&1 || { echo >&2 "[ERROR] Please install \"make\""; exit 1; }
type autoconf >> $DIR/install.log 2>&1 || { echo >&2 "[ERROR] Please install \"autoconf\""; exit 1; }
type automake >> $DIR/install.log 2>&1 || { echo >&2 "[ERROR] Please install \"automake\""; exit 1; }
type gcc >> $DIR/install.log 2>&1 || { echo >&2 "[ERROR] Please install \"gcc\""; exit 1; }
type m4 >> $DIR/install.log 2>&1 || { echo >&2 "[ERROR] Please install \"m4\""; exit 1; }
rm -r -f install_data/ >> $DIR/install.log 2>&1
rm -r -f php5/ >> $DIR/install.log 2>&1
mkdir -m 0777 install_data >> $DIR/install.log 2>&1
mkdir -m 0777 php5 >> $DIR/install.log 2>&1
type make >> "$DIR/install.log" 2>&1 || { echo >&2 "[ERROR] Please install \"make\""; exit 1; }
type autoconf >> "$DIR/install.log" 2>&1 || { echo >&2 "[ERROR] Please install \"autoconf\""; exit 1; }
type automake >> "$DIR/install.log" 2>&1 || { echo >&2 "[ERROR] Please install \"automake\""; exit 1; }
type libtool >> "$DIR/install.log" 2>&1 || { echo >&2 "[ERROR] Please install \"libtool\""; exit 1; }
type gcc >> "$DIR/install.log" 2>&1 || { echo >&2 "[ERROR] Please install \"gcc\""; exit 1; }
type m4 >> "$DIR/install.log" 2>&1 || { echo >&2 "[ERROR] Please install \"m4\""; exit 1; }
rm -r -f install_data/ >> "$DIR/install.log" 2>&1
rm -r -f php5/ >> "$DIR/install.log" 2>&1
mkdir -m 0777 install_data >> "$DIR/install.log" 2>&1
mkdir -m 0777 php5 >> "$DIR/install.log" 2>&1
cd install_data
set -e
#PHP 5
echo -n "[PHP5] downloading..."
wget http://php.net/get/php-5.4.11.tar.gz/from/this/mirror -O php-5.4.11.tar.gz >> $DIR/install.log 2>&1
echo -n " extracting..."
tar -zxvf php-5.4.11.tar.gz >> $DIR/install.log 2>&1
rm -f php-5.4.11.tar.gz >> $DIR/install.log 2>&1
mv php-5.4.11 php
echo -n "[PHP] downloading $PHP_VERSION..."
wget http://php.net/get/php-$PHP_VERSION.tar.gz/from/this/mirror -q -O - | tar -zx >> "$DIR/install.log" 2>&1
mv php-$PHP_VERSION php
echo " done!"
#zlib
echo -n "[zlib] downloading..."
wget http://zlib.net/zlib-1.2.7.tar.gz -O zlib-1.2.7.tar.gz >> $DIR/install.log 2>&1
echo -n " extracting..."
tar -zxvf zlib-1.2.7.tar.gz >> $DIR/install.log 2>&1
rm -f zlib-1.2.7.tar.gz >> $DIR/install.log 2>&1
mv zlib-1.2.7 zlib
echo -n "[zlib] downloading $ZLIB_VERSION..."
wget http://zlib.net/zlib-$ZLIB_VERSION.tar.gz -q -O - | tar -zx >> "$DIR/install.log" 2>&1
mv zlib-$ZLIB_VERSION zlib
echo -n " checking..."
cd zlib
./configure --prefix=$DIR/install_data/php/ext/zlib \
--static >> $DIR/install.log 2>&1
./configure --prefix="$DIR/install_data/php/ext/zlib" \
--static >> "$DIR/install.log" 2>&1
echo -n " compiling..."
make >> $DIR/install.log 2>&1
make >> "$DIR/install.log" 2>&1
echo -n " installing..."
make install >> $DIR/install.log 2>&1
make install >> "$DIR/install.log" 2>&1
echo -n " cleaning..."
cd ..
rm -r -f ./zlib
echo " done!"
#OpenSSL
#echo -n "[OpenSSL] downloading..."
#wget ftp://ftp.openssl.org/source/openssl-1.0.1c.tar.gz -O openssl-1.0.1c.tar.gz >> $DIR/install.log 2>&1
#echo -n " extracting..."
#tar -zxvf openssl-1.0.1c.tar.gz >> $DIR/install.log 2>&1
#rm -f openssl-1.0.1c.tar.gz >> $DIR/install.log 2>&1
#mv openssl-1.0.1c openssl
#Readline
#echo -n "[Readline] downloading $READLINE_VERSION..."
#wget ftp://ftp.cwru.edu/pub/bash/readline-$READLINE_VERSION.tar.gz -q -O - | tar -xz >> "$DIR/install.log" 2>&1
#mv readline-$READLINE_VERSION readline
#echo -n " checking..."
#cd openssl
#./config --prefix=$DIR/install_data/php/ext/openssl >> $DIR/install.log 2>&1
#cd readline
#./configure --prefix="$DIR/install_data/php/ext/readline" \
#--disable-shared >> "$DIR/install.log" 2>&1
#echo -n " compiling..."
#make >> $DIR/install.log 2>&1
#make >> "$DIR/install.log" 2>&1
#echo -n " installing..."
#make install >> $DIR/install.log 2>&1
#make install >> "$DIR/install.log" 2>&1
#echo -n " cleaning..."
#cd ..
#rm -r -f ./openssl
#rm -r -f ./readine
#echo " done!"
#--with-readline=$DIR/install_data/php/ext/readline
#GMP
echo -n "[GMP] downloading..."
wget ftp://ftp.gmplib.org/pub/gmp-5.1.0/gmp-5.1.0.tar.bz2 -O gmp-5.1.0.tar.bz2 >> $DIR/install.log 2>&1
echo -n " extracting..."
tar -jxvf gmp-5.1.0.tar.bz2 >> $DIR/install.log 2>&1
rm -f gmp-5.1.0.tar.bz2 >> $DIR/install.log 2>&1
mv gmp-5.1.0 gmp
echo -n "[GMP] downloading $GMP_VERSION..."
wget ftp://ftp.gmplib.org/pub/gmp-$GMP_VERSION/gmp-$GMP_VERSION.tar.bz2 -q -O - | tar -xj >> "$DIR/install.log" 2>&1
mv gmp-$GMP_VERSION gmp
echo -n " checking..."
cd gmp
./configure --prefix=$DIR/install_data/php/ext/gmp \
--disable-shared >> $DIR/install.log 2>&1
./configure --prefix="$DIR/install_data/php/ext/gmp" \
--disable-assembly \
--disable-shared >> "$DIR/install.log" 2>&1
echo -n " compiling..."
make >> $DIR/install.log 2>&1
make >> "$DIR/install.log" 2>&1
echo -n " installing..."
make install >> $DIR/install.log 2>&1
make install >> "$DIR/install.log" 2>&1
echo -n " cleaning..."
cd ..
rm -r -f ./gmp
echo " done!"
echo -n "[cURL] downloading..."
wget https://github.com/bagder/curl/archive/master.tar.gz --no-check-certificate -O curl-master.tar.gz >> $DIR/install.log 2>&1
echo -n " extracting..."
tar -zxvf curl-master.tar.gz >> $DIR/install.log 2>&1
rm -f curl-master.tar.gz >> $DIR/install.log 2>&1
mv curl-master curl
echo -n "[cURL] downloading $CURL_VERSION..."
wget https://github.com/bagder/curl/archive/$CURL_VERSION.tar.gz --no-check-certificate -q -O - | tar -zx >> "$DIR/install.log" 2>&1
mv curl-$CURL_VERSION curl
echo -n " checking..."
cd curl
./buildconf >> $DIR/install.log 2>&1
./configure --prefix=$DIR/install_data/php/ext/curl \
--disable-shared >> $DIR/install.log 2>&1
./buildconf >> "$DIR/install.log" 2>&1
./configure --prefix="$DIR/install_data/php/ext/curl" \
--disable-shared >> "$DIR/install.log" 2>&1
echo -n " compiling..."
make >> $DIR/install.log 2>&1
make >> "$DIR/install.log" 2>&1
echo -n " installing..."
make install >> $DIR/install.log 2>&1
make install >> "$DIR/install.log" 2>&1
echo -n " cleaning..."
cd ..
rm -r -f ./curl
echo " done!"
#pthreads
echo -n "[PHP pthreads] downloading..."
wget https://github.com/krakjoe/pthreads/archive/master.tar.gz --no-check-certificate -O pthreads-master.tar.gz >> $DIR/install.log 2>&1
echo -n " extracting..."
tar -zxvf pthreads-master.tar.gz >> $DIR/install.log 2>&1
rm -f pthreads-master.tar.gz >> $DIR/install.log 2>&1
mv pthreads-master $DIR/install_data/php/ext/pthreads
echo -n "[PHP pthreads] downloading $PTHREADS_VERSION..."
wget https://github.com/krakjoe/pthreads/archive/$PTHREADS_VERSION.tar.gz --no-check-certificate -q -O - | tar -zx >> "$DIR/install.log" 2>&1
mv pthreads-$PTHREADS_VERSION "$DIR/install_data/php/ext/pthreads"
echo " done!"
#--with-openssl=$DIR/install_data/php/ext/openssl
echo -n "[PHP5] checking..."
echo -n "[PHP]"
set +e
if which free >/dev/null; then
MAX_MEMORY=$(free -m | awk '/^Mem:/{print $2}')
else
MAX_MEMORY=$(top -l 1 | grep PhysMem: | awk '{print $10}' | tr -d 'a-zA-Z')
fi
if [ $MAX_MEMORY -gt 2048 ]
then
echo -n " enabling optimizations..."
OPTIMIZATION="--enable-inline-optimization "
else
OPTIMIZATION=""
fi
set -e
echo -n " checking..."
cd php
./buildconf --force >> $DIR/install.log 2>&1
./configure --prefix=$DIR/php5 \
--exec-prefix=$DIR/php5 \
rm -rf ./aclocal.m4 >> "$DIR/install.log" 2>&1
rm -rf ./autom4te.cache/ >> "$DIR/install.log" 2>&1
rm -f ./configure >> "$DIR/install.log" 2>&1
./buildconf --force >> "$DIR/install.log" 2>&1
./configure $OPTIMIZATION--prefix="$DIR/php5" \
--exec-prefix="$DIR/php5" \
--enable-embedded-mysqli \
--enable-bcmath \
--with-gmp=$DIR/install_data/php/ext/gmp \
--with-curl=$DIR/install_data/php/ext/curl \
--with-zlib=$DIR/install_data/php/ext/zlib \
--with-gmp="$DIR/install_data/php/ext/gmp" \
--with-curl="$DIR/install_data/php/ext/curl" \
--with-zlib="$DIR/install_data/php/ext/zlib" \
--disable-libxml \
--disable-xml \
--disable-dom \
@ -141,16 +159,18 @@ cd php
--enable-pcntl \
--enable-pthreads \
--enable-maintainer-zts \
--enable-cli >> $DIR/install.log 2>&1
--enable-zend-signals \
--with-zend-vm=$ZEND_VM \
--enable-cli >> "$DIR/install.log" 2>&1
echo -n " compiling..."
make >> $DIR/install.log 2>&1
make >> "$DIR/install.log" 2>&1
echo -n " installing..."
make install >> $DIR/install.log 2>&1
make install >> "$DIR/install.log" 2>&1
echo " done!"
cd $DIR
cd "$DIR"
echo -n "[INFO] Cleaning up..."
rm -r -f install_data/ >> $DIR/install.log 2>&1
date >> $DIR/install.log 2>&1
rm -r -f install_data/ >> "$DIR/install.log" 2>&1
date >> "$DIR/install.log" 2>&1
echo " done!"
echo "[PocketMine] You should start the server now using \"./start.sh\""
echo "[PocketMine] If it doesn't works, please send the \"install.log\" file to the Bug Tracker"

View File

@ -29,37 +29,113 @@ class BanAPI{
private $server;
private $whitelist;
private $banned;
private $ops;
private $bannedIPs;
private $cmdWL = array();
function __construct(PocketMinecraftServer $server){
$this->server = $server;
}
public function init(){
console("[INFO] Loading authentication lists...");
$this->whitelist = new Config(FILE_PATH."white-list.txt", CONFIG_LIST);
$this->bannedIPs = new Config(FILE_PATH."banned-ips.txt", CONFIG_LIST);
$this->banned = new Config(FILE_PATH."banned.txt", CONFIG_LIST);
$this->whitelist = new Config(DATA_PATH."white-list.txt", CONFIG_LIST);
$this->bannedIPs = new Config(DATA_PATH."banned-ips.txt", CONFIG_LIST);
$this->banned = new Config(DATA_PATH."banned.txt", CONFIG_LIST);
$this->ops = new Config(DATA_PATH."ops.txt", CONFIG_LIST);
$this->server->api->console->register("banip", "Manages IP Banning", array($this, "commandHandler"));
$this->server->api->console->register("ban", "Manages Bannning", array($this, "commandHandler"));
$this->server->api->console->register("kick", "Kicks a player", array($this, "commandHandler"));
$this->server->api->console->register("whitelist", "Manages White-listing", array($this, "commandHandler"));
$this->server->api->console->register("op", "Ops a player", array($this, "commandHandler"));
$this->server->api->console->register("deop", "De-ops a player", array($this, "commandHandler"));
$this->server->api->console->register("sudo", "Run a command as a player", array($this, "commandHandler"));
$this->server->api->console->alias("ban-ip", "banip add");
$this->server->api->console->alias("banlist", "ban list");
$this->server->api->console->alias("pardon", "ban remove");
$this->server->api->console->alias("pardon-ip", "banip remove");
$this->server->addHandler("console.command", array($this, "permissionsCheck"), 1);
$this->cmdWhitelist("help");
}
public function commandHandler($cmd, $params){
public function cmdWhitelist($cmd){
$this->cmdWhitelist[strtolower(trim($cmd))] = true;
}
public function isOp($username){
if($this->server->api->dhandle("op.check", $username) === true){
return true;
}elseif($this->ops->exists($username)){
return true;
}
return false;
}
public function permissionsCheck($data, $event){
if(isset($this->cmdWhitelist[$data["cmd"]])){
return true;
}
if($data["issuer"] instanceof Player){
if($this->server->api->handle("console.check", $data) === true or $this->isOp($data["issuer"]->username)){
return true;
}
}elseif($data["issuer"] === "console"){
return true;
}
return false;
}
public function commandHandler($cmd, $params, $issuer, $alias){
$output = "";
switch($cmd){
case "sudo":
$target = array_shift($params);
$player = $this->server->api->player->get($target);
if(!($player instanceof Player)){
$output .= "Player not connected.\n";
break;
}
$this->server->api->console->run(implode(" ", $params), $player);
$output .= "Command ran.\n";
break;
case "op":
$user = array_shift($params);
if($user == ""){
break;
}
$this->ops->set($user);
$this->ops->save();
$output .= $user." is now op\n";
$this->server->api->chat->sendTo(false, "You are now op.", $user);
break;
case "deop":
$user = array_shift($params);
if($user == ""){
break;
}
$this->ops->remove($user);
$this->ops->save();
$output .= $user." is not longer op\n";
$this->server->api->chat->sendTo(false, "You are not longer op.", $user);
break;
case "kick":
if(!isset($params[0])){
console("[INFO] Usage: /kick <playername> [reason]");
$output .= "Usage: /kick <playername> [reason]\n";
}else{
$name = array_shift($params);
$player = $this->server->api->player->get($name);
if($player === false){
console("[ERROR] Player \"".$name."\" does not exist");
$output .= "Player \"".$name."\" does not exist\n";
}else{
$reason = implode(" ", $params);
$reason = $reason == "" ? "No reason":$reason;
$player->close("You have been kicked: ".$reason);
console("[INFO] Player \"".$player->username."\" has been kicked: $reason");
if($issuer instanceof Player){
$this->server->api->chat->broadcast($player->username." has been kicked by ".$issuer->username.": $reason\n");
}else{
$this->server->api->chat->broadcast($player->username." has been kicked: $reason\n");
}
}
}
break;
@ -70,34 +146,34 @@ class BanAPI{
$user = trim(implode(" ", $params));
$this->whitelist->remove($user);
$this->whitelist->save();
console("[INFO] Player \"$user\" removed from white-list");
$output .= "Player \"$user\" removed from white-list\n";
break;
case "add":
$user = trim(implode(" ", $params));
$this->whitelist->set($user);
$this->whitelist->save();
console("[INFO] Player \"$user\" added to white-list");
$output .= "Player \"$user\" added to white-list\n";
break;
case "reload":
$this->whitelist = $this->load(FILE_PATH."white-list.txt", CONFIG_LIST);
$this->whitelist = new Config(DATA_PATH."white-list.txt", CONFIG_LIST);
break;
case "list":
console("[INFO] White-list: ".implode(", ", $this->whitelist->getAll(true)));
$output .= "White-list: ".implode(", ", $this->whitelist->getAll(true))."\n";
break;
case "on":
case "true":
case "1":
console("[INFO] White-list turned on");
$output .= "White-list turned on\n";
$this->server->api->setProperty("white-list", true);
break;
case "off":
case "false":
case "0":
console("[INFO] White-list turned off");
$output .= "White-list turned off\n";
$this->server->api->setProperty("white-list", false);
break;
default:
console("[INFO] Usage: /whitelist <on | off | add | remove | reload | list> [username]");
$output .= "Usage: /whitelist <on | off | add | remove | reload | list> [username]\n";
break;
}
break;
@ -109,23 +185,23 @@ class BanAPI{
$ip = trim(implode($params));
$this->bannedIPs->remove($ip);
$this->bannedIPs->save();
console("[INFO] IP \"$ip\" removed from ban list");
$output .= "IP \"$ip\" removed from ban list\n";
break;
case "add":
case "ban":
$ip = trim(implode($params));
$this->bannedIPs->set($ip);
$this->bannedIPs->save();
console("[INFO] IP \"$ip\" added to ban list");
$output .= "IP \"$ip\" added to ban list\n";
break;
case "reload":
$this->bannedIPs = new Config(FILE_PATH."banned-ips.txt", CONFIG_LIST);
$this->bannedIPs = new Config(DATA_PATH."banned-ips.txt", CONFIG_LIST);
break;
case "list":
console("[INFO] IP ban list: ".implode(", ", $this->bannedIPs->getAll(true)));
$output .= "IP ban list: ".implode(", ", $this->bannedIPs->getAll(true))."\n";
break;
default:
console("[INFO] Usage: /banip <add | remove | list | reload> [IP]");
$output .= "Usage: /banip <add | remove | list | reload> [IP]\n";
break;
}
break;
@ -137,11 +213,11 @@ class BanAPI{
$user = trim(implode($params));
$this->banned->remove($user);
$this->banned->save();
console("[INFO] Player \"$user\" removed from ban list");
$output .= "Player \"$user\" removed from ban list\n";
break;
case "add":
case "ban":
$user = trim(implode($params));
$user = array_shift($params);
$this->banned->set($user);
$this->banned->save();
$player = $this->server->api->player->get($user);
@ -149,20 +225,27 @@ class BanAPI{
$player->close("You have been banned");
}
$this->server->api->chat->broadcast("$user has been banned");
console("[INFO] Player \"$user\" added to ban list");
if($issuer instanceof Player){
$this->server->api->chat->broadcast($user." has been banned by ".$issuer->username."\n");
}else{
$this->server->api->chat->broadcast($user." has been banned\n");
}
$this->kick($user, "Banned");
$output .= "Player \"$user\" added to ban list\n";
break;
case "reload":
$this->banned = new Config(FILE_PATH."banned.txt", CONFIG_LIST);
$this->banned = new Config(DATA_PATH."banned.txt", CONFIG_LIST);
break;
case "list":
console("[INFO] Ban list: ".implode(", ", $this->banned->getAll(true)));
$output .= "Ban list: ".implode(", ", $this->banned->getAll(true))."\n";
break;
default:
console("[INFO] Usage: /ban <add | remove | list | reload> [player]");
$output .= "Usage: /ban <add | remove | list | reload> [player]\n";
break;
}
break;
}
return $output;
}
public function ban($username){
@ -181,6 +264,10 @@ class BanAPI{
$this->commandHandler("banip", array("pardon", $ip));
}
public function kick($username, $reason = "No Reason"){
$this->commandHandler("kick", array($username, $reason));
}
public function reload(){
$this->commandHandler("ban", array("reload"));
$this->commandHandler("banip", array("reload"));
@ -213,4 +300,4 @@ class BanAPI{
}
return false;
}
}
}

View File

@ -25,6 +25,7 @@ the Free Software Foundation, either version 3 of the License, or
*/
define("BLOCK_UPDATE_NORMAL", 0);
define("BLOCK_UPDATE_RANDOM", 1);
define("BLOCK_UPDATE_SCHEDULED", 2);
@ -32,234 +33,218 @@ define("BLOCK_UPDATE_WEAK", 3);
class BlockAPI{
private $server;
public static function fromString($str, $multiple = false){
if($multiple === true){
$blocks = array();
foreach(explode(",",$str) as $b){
$blocks[] = BlockAPI::fromString($b, false);
}
return $blocks;
}else{
$b = explode(":", str_replace(" ", "_", trim($str)));
if(!isset($b[1])){
$meta = 0;
}else{
$meta = ((int) $b[1]) & 0xFFFF;
}
if(defined(strtoupper($b[0]))){
$item = BlockAPI::getItem(constant(strtoupper($b[0])), $meta);
if($item->getID() === AIR and strtoupper($b[0]) !== "AIR"){
$item = BlockAPI::getItem(((int) $b[0]) & 0xFFFF, $meta);
}
}else{
$item = BlockAPI::getItem(((int) $b[0]) & 0xFFFF, $meta);
}
return $item;
}
}
public static function get($id, $meta = 0, $v = false){
$id = (int) $id;
if(isset(Block::$class[$id])){
$classname = Block::$class[$id];
$b = new $classname($meta);
}else{
$b = new GenericBlock($id, $meta);
}
if($v instanceof Vector3){
$b->position($v);
}
return $b;
}
public static function getItem($id, $meta = 0, $count = 1){
$id = (int) $id;
if(isset(Item::$class[$id])){
$classname = Item::$class[$id];
$i = new $classname($meta, $count);
}else{
$i = new Item($id, $meta, $count);
}
return $i;
}
public function setBlock(Vector3 $block, $id, $meta, $update = true, $tiles = false){
if(($block instanceof Vector3) or (($block instanceof Block) and $block->inWorld === true)){
$this->server->api->level->setBlock($block->x, $block->y, $block->z, (int) $id, (int) $meta, $update, $tiles);
return true;
}
return false;
}
public function getBlock($x, $y = 0, $z = 0){
if($x instanceof Vector3){
$y = $x->y;
$z = $x->z;
$x = $x->x;
}
$b = $this->server->api->level->getBlock($x, $y, $z);
return BlockAPI::get($b[0], $b[1], new Vector3($b[2][0], $b[2][1], $b[2][2]));
}
public function getBlockFace(Block $block, $face){
return $this->getBlock($block->getSide($face));
}
function __construct(PocketMinecraftServer $server){
$this->server = $server;
}
public function init(){
$this->server->addHandler("block.update", array($this, "updateBlockRemote"), 1);
$this->server->addHandler("player.block.break", array($this, "blockBreak"), 1);
$this->server->addHandler("player.block.action", array($this, "blockAction"), 1);
$this->server->api->console->register("give", "Give items to a player", array($this, "commandHandler"));
}
public function commandHandler($cmd, $params){
public function commandHandler($cmd, $params, $issuer, $alias){
$output = "";
switch($cmd){
case "give":
if(!isset($params[0]) or !isset($params[1])){
console("[INFO] Usage: /give <username> <item> [amount] [damage]");
$output .= "Usage: /give <username> <item> [amount] [damage]\n";
break;
}
$username = $params[0];
$b = explode(":", $params[1]);
if(!isset($b[1])){
$meta = 0;
}else{
$meta = (int) $b[1];
}
$block = ((int) $b[0]) & 0xFFFF;
$item = BlockAPI::fromString($params[1]);
if(!isset($params[2])){
$amount = 64;
$item->count = $item->getMaxStackSize();
}else{
$amount = (int) $params[2];
}
if(isset($params[3])){
$meta = (int) $params[3];
$item->count = (int) $params[2];
}
if(($player = $this->server->api->player->get($username)) !== false){
$this->drop($player->entity->x - 0.5, $player->entity->y, $player->entity->z - 0.5, $block, $meta, $amount);
console("[INFO] Giving ".$amount." of ".$block.":".$meta." to ".$username);
$this->drop(new Vector3($player->entity->x - 0.5, $player->entity->y, $player->entity->z - 0.5), $item, true);
$output .= "Giving ".$item->count." of ".$item->getName()." (".$item->getID().":".$item->getMetadata().") to ".$username."\n";
}else{
console("[INFO] Unknown player");
$output .= "Unknown player\n";
}
break;
}
return $output;
}
private function cancelAction($block){
$this->server->api->dhandle("block.change", array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2],
"block" => $block[0],
"meta" => $block[1],
"fake" => true,
private function cancelAction(Block $block, Player $player){
$player->dataPacket(MC_UPDATE_BLOCK, array(
"x" => $block->x,
"y" => $block->y,
"z" => $block->z,
"block" => $block->getID(),
"meta" => $block->getMetadata()
));
return false;
}
public function blockBreak($data, $event){
if($event !== "player.block.break"){
return;
public function playerBlockBreak(Player $player, Vector3 $vector){
$target = $this->getBlock($vector);
$item = $player->equipment;
if($this->server->api->dhandle("player.block.touch", array("type" => "break", "player" => $player, "target" => $target, "item" => $item)) === false){
return $this->cancelAction($target, $player);
}
$target = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"]);
if(isset(Material::$unbreakable[$target[0]])){
return $this->cancelAction($target);
if(!$target->isBreakable($item, $player) or $player->gamemode === ADVENTURE or ($player->lastBreak + $target->getBreakTime($item, $player)) >= microtime(true)){
return $this->cancelAction($target, $player);
}
$drop = array(
$target[0], //Block
$target[1], //Meta
1, //Count
);
switch($target[0]){
case 1:
$drop[0] = 4;
break;
case 16:
$drop = array(263, 0, 1);
break;
case 21:
$drop = array(351, 4, mt_rand(4, 8));
break;
case 62:
$drop[0] = 61;
case 50: //Drop without metadata
case 53:
case 54:
case 61:
case 65:
case 67:
case 96:
case 107:
case 108:
case 109:
$drop[1] = 0;
break;
case 56:
$drop = array(264, 0, 1);
break;
case 73:
case 74:
$drop = array(351, 4, mt_rand(4, 5));
break;
case 18:
$drop = false;
if(mt_rand(1,20) === 1){ //Saplings
$drop = array(6, $target[1], 1);
}
if($target[1] === 0 and mt_rand(1,200) === 1){ //Apples
$this->drop($data["x"], $data["y"], $data["z"], 260, 0, 1);
}
break;
case 59:
if($target[1] >= 0x07){ //Seeds
$drop = array(296, 0, 1);
$this->drop($data["x"], $data["y"], $data["z"], 295, 0, mt_rand(0,3));
}else{
$drop = array(295, 0, 1);
}
break;
case 31:
$drop = false;
if(mt_rand(1,10) === 1){ //Seeds
$drop = array(295, 0, 1);
}
break;
case 20:
$drop = false;
break;
case 30:
$drop = false;
break;
case 51:
$drop = false;
break;
case 52:
$drop = false;
break;
case 43:
$drop = array(
44,
$target[1],
2,
);
break;
case 46: //TNT
if(($player = $this->server->api->player->getByEID($data["eid"])) !== false){
$player->dataPacket(MC_EXPLOSION, array(
"x" => $data["x"],
"y" => $data["y"],
"z" => $data["z"],
"radius" => 2,
"records" => array(),
));
}
break;
case 60:
case 2:
$drop = array(3, 0, 1);
break;
case 64: //Wood Door
case 71: //Iron Door
$drop = array(($target[0] === 64 ? 324:330), 0, 1);
if(($target[1] & 0x08) === 0x08){
$down = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
if($down[0] === $target[0]){
$data2 = $data;
--$data2["y"];
$this->server->trigger("player.block.break", $data2);
}
}else{
$up = $this->server->api->level->getBlock($data["x"], $data["y"] + 1, $data["z"]);
if($up[0] === $target[0]){
$data2 = $data;
++$data2["y"];
$this->server->trigger("player.block.break", $data2);
}
}
break;
if($this->server->api->dhandle("player.block.break", array("player" => $player, "target" => $target, "item" => $item)) !== false){
$player->lastBreak = microtime(true);
$drops = $target->getDrops($item, $player);
$target->onBreak($this, $item, $player);
}else{
return $this->cancelAction($target, $player);
}
if($drop !== false and $drop[0] !== 0 and $drop[2] > 0){
$this->drop($data["x"], $data["y"], $data["z"], $drop[0], $drop[1] & 0x0F, $drop[2] & 0xFF);
if(count($drops) > 0){
foreach($drops as $drop){
$this->drop($target, BlockAPI::getItem($drop[0] & 0xFFFF, $drop[1] & 0xFFFF, $drop[2] & 0xFF));
}
}
$this->server->trigger("player.block.break", $data);
return false;
}
public function drop($x, $y, $z, $block, $meta, $stack = 1){
if($block === 0 or $stack <= 0 or $this->server->gamemode === 1){
public function drop(Vector3 $pos, Item $item, $force = false){
if($item->getID() === AIR or $item->count <= 0 or ($this->server->gamemode === CREATIVE and $force !== true)){
return;
}
$data = array(
"x" => $x,
"y" => $y,
"z" => $z,
"meta" => $meta,
"stack" => $stack,
"x" => $pos->x + mt_rand(2, 8) / 10,
"y" => $pos->y + 0.19,
"z" => $pos->z + mt_rand(2, 8) / 10,
"item" => $item,
);
$data["x"] += mt_rand(2, 8) / 10;
$data["y"] += 0.19;
$data["z"] += mt_rand(2, 8) / 10;
if($this->server->api->handle("block.drop", $data) !== false){
for($count = $stack; $count > 0; ){
$data["stack"] = min(64, $count);
$count -= $data["stack"];
$e = $this->server->api->entity->add(ENTITY_ITEM, $block, $data);
$this->server->api->entity->spawnToAll($e->eid);
if($this->server->api->handle("item.drop", $data) !== false){
for($count = $item->count; $count > 0; ){
$item->count = min($item->getMaxStackSize(), $count);
$count -= $item->count;
$server = ServerAPI::request();
$e = $server->api->entity->add(ENTITY_ITEM, $item->getID(), $data);
//$e->speedX = mt_rand(-10, 10) / 100;
//$e->speedY = mt_rand(0, 5) / 100;
//$e->speedZ = mt_rand(-10, 10) / 100;
$server->api->entity->spawnToAll($e->eid);
}
}
}
public function blockAction($data, $event){
if($event !== "player.block.action"){
return;
}
if($data["face"] < 0 or $data["face"] > 5){
public function playerBlockAction(Player $player, Vector3 $vector, $face, $fx, $fy, $fz){
if($face < 0 or $face > 5){
return false;
}
$data["original"] = array($data["block"], $data["meta"]);
$target = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"]);
if($target[0] === 0){ //If no block exists
$this->cancelAction($target);
$block = $this->server->api->level->getBlockFace($target, $data["face"]);
return $this->cancelAction($block);
$target = $this->getBlock($vector);
$block = $this->getBlockFace($target, $face);
$item = $player->equipment;
if($target->getID() === AIR){ //If no block exists
$this->cancelAction($target, $player);
return $this->cancelAction($block, $player);
}
if($this->server->api->dhandle("player.block.touch", array("type" => "place", "player" => $player, "block" => $block, "target" => $target, "item" => $item)) === false){
return $this->cancelAction($block, $player);
}
$cancelPlace = false;
if(isset(Material::$activable[$target[0]])){
if($target->isActivable === true){
if($this->server->api->dhandle("player.block.activate", array("player" => $player, "block" => $block, "target" => $target, "item" => $item)) !== false and $target->onActivate($this, $item, $player) === true){
return false;
}
}
if($player->gamemode === ADVENTURE){ //Adventure mode!!
return $this->cancelAction($block, $player);
}
/*if(isset(Material::$activable[$target[0]])){
switch($target[0]){
case 54:
$cancelPlace = true;
@ -286,310 +271,48 @@ class BlockAPI{
"title" => "Furnace",
));
break;
case 6:
if($data["block"] === 351 and $data["meta"] === 0x0F){ //Bonemeal
Sapling::growTree($this->server->api->level, $target, $target[1] & 0x03);
$cancelPlace = true;
}
break;
case 2:
case 3:
if($data["block"] === 292){ //Hoe
$data["block"] = 60;
$data["meta"] = 0;
$this->server->handle("player.block.update", $data);
$cancelPlace = true;
}
case 59:
case 105:
if($data["block"] === 351 and $data["meta"] === 0x0F){ //Bonemeal
$data["block"] = $target[0];
$data["meta"] = 0x07;
$this->server->handle("player.block.place", $data);
$cancelPlace = true;
}
break;
case 64: //Door
if(($target[1] & 0x08) === 0x08){
$down = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
if($down[0] === 64){
$down[1] = $down[1] ^ 0x04;
$data2 = array(
"x" => $data["x"],
"z" => $data["z"],
"y" => $data["y"] - 1,
"block" => $down[0],
"meta" => $down[1],
"eid" => $data["eid"],
);
if($this->server->handle("player.block.update", $data2) !== false){
$this->updateBlocksAround($data["x"], $data["y"], $data["z"], BLOCK_UPDATE_NORMAL);
}
}
}else{
$data["block"] = $target[0];
$data["meta"] = $target[1] ^ 0x04;
if($this->server->handle("player.block.update", $data) !== false){
$up = $this->server->api->level->getBlock($data["x"], $data["y"] + 1, $data["z"]);
if($up[0] === 64){
$data2 = $data;
$data2["meta"] = $up[1];
++$data2["y"];
$this->updateBlocksAround($data2["x"], $data2["y"], $data2["z"], BLOCK_UPDATE_NORMAL);
}
$this->updateBlocksAround($data["x"], $data["y"], $data["z"], BLOCK_UPDATE_NORMAL);
}
}
$cancelPlace = true;
break;
case 96: //Trapdoor
case 107: //Fence gates
$data["block"] = $target[0];
$data["meta"] = $target[1] ^ 0x04;
$this->server->handle("player.block.update", $data);
$cancelPlace = true;
break;
default:
$cancelPlace = true;
break;
}
}
}*/
if($cancelPlace === true){
if($block->y > 127 or $block->y < 0){
return false;
}
$replace = false;
switch($data["block"]){
case 44: //Slabs
if($data["face"] === 0){
break;
}elseif($data["face"] === 1){
if(($target[1] & 0x07) === ($data["meta"] & 0x07) and $target[0] === 44){
$replace = true;
$data["block"] = 43;
$data["meta"] = $data["meta"] & 0x07;
}
}else{
$data2 = $data;
BlockFace::setPosition($data2, $data["face"]);
$b = $this->server->api->level->getBlock($data2["x"], $data2["y"], $data2["z"]);
if($b[0] === 44 and ($b[1] & 0x07) === ($data["meta"] & 0x07) and $b[0] === 44){
$data = $data2;
$replace = true;
$data["block"] = 43;
$data["meta"] = $data["meta"] & 0x07;
}
}
break;
}
if($replace === false){
BlockFace::setPosition($data, $data["face"]);
}
if($data["y"] >= 127){
return false;
}
$block = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"]);
if($replace === false and !isset(Material::$replaceable[$block[0]])){
return $this->cancelAction($block);
}
if(isset(Material::$placeable[$data["block"]])){
$data["block"] = Material::$placeable[$data["block"]] === true ? $data["block"]:Material::$placeable[$data["block"]];
}else{
return $this->cancelAction($block);
}
$entity = $this->server->api->entity->get($data["eid"]);
if(($entity instanceof Entity) !== true){
return $this->cancelAction($block); //No Entity WTF?
}
if(!isset(Material::$transparent[$data["block"]]) and $entity->inBlock($block[2][0], $block[2][1], $block[2][2])){
return $this->cancelAction($block); //Entity in block
if($item->isActivable === true and $item->onActivate($this, $player, $block, $target, $face, $fx, $fy, $fz)){
return $this->cancelAction($block, $player);
}
$direction = $entity->getDirection();
switch($data["block"]){
case 6:
if($target[0] === 60){
break;
}
case 37:
case 38:
if(($target[0] !== 2 and $target[0] !== 3) or $data["face"] !== 1){
return false;
}
break;
case 39://Mushrooms
case 40:
$blockDown = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
if(isset(Material::$transparent[$blockDown[0]])){
return false;
}
break;
case 83: //Sugarcane
$blockDown = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
if($blockDown[0] !== 2 and $blockDown[0] !== 3 and $blockDown[0] !== 12){
return false;
}
$block0 = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"] + 1);
$block1 = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"] - 1);
$block2 = $this->server->api->level->getBlock($data["x"] + 1, $data["y"], $data["z"]);
$block3 = $this->server->api->level->getBlock($data["x"] - 1, $data["y"], $data["z"]);
if($block0[0] === 9 or $block0[0] === 8 or $block1[0] === 9 or $block1[0] === 8 or $block2[0] === 9 or $block2[0] === 8 or $block3[0] === 9 or $block3[0] === 8){
}else{
return false;
}
break;
case 50: //Torch
if(isset(Material::$transparent[$target[0]])){
return false;
}
$faces = array(
0 => 6,
1 => 5,
2 => 4,
3 => 3,
4 => 2,
5 => 1,
);
if(!isset($faces[$data["face"]])){
return false;
}
$data["meta"] = $faces[$data["face"]];
break;
case 53://Stairs
case 67:
case 108:
$faces = array(
0 => 0,
1 => 2,
2 => 1,
3 => 3,
);
$data["meta"] = $faces[$direction] & 0x03;
break;
case 96: //trapdoor
if(isset(Material::$transparent[$target[0]])){
return false;
}
$faces = array(
2 => 0,
3 => 1,
4 => 2,
5 => 3,
);
if(!isset($faces[$data["face"]])){
return false;
}
$data["meta"] = $faces[$data["face"]] & 0x03;
break;
case 107: //Fence gate
$faces = array(
0 => 3,
1 => 0,
2 => 1,
3 => 2,
);
$data["meta"] = $faces[$direction] & 0x03;
break;
case 64://Door placing
case 71:
if($data["face"] !== 1){
return false;
}
$blockUp = $this->server->api->level->getBlock($data["x"], $data["y"] + 1, $data["z"]);
$blockDown = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
if(!isset(Material::$replaceable[$blockUp[0]]) or isset(Material::$transparent[$blockDown[0]])){
return false;
}else{
$data2 = $data;
$data2["meta"] = 0x08;
$data["meta"] = $direction & 0x03;
$face = array(
0 => 3,
1 => 4,
2 => 2,
3 => 5,
);
$next = $this->server->api->level->getBlockFace($block, $face[(($direction + 2) % 4)]);
if($next[0] === $data["block"]){ //Door hinge
$data2["meta"] = $data2["meta"] | 0x01;
}
++$data2["y"];
$this->server->handle("player.block.place", $data2);
}
break;
case 54:
case 61:
$faces = array(
0 => 4,
1 => 2,
2 => 5,
3 => 3,
);
$data["meta"] = $faces[$direction];
break;
case 26: //bed
$face = array(
0 => 3,
1 => 4,
2 => 2,
3 => 5,
);
$next = $this->server->api->level->getBlockFace($block, $face[(($direction + 3) % 4)]);
if(!isset(Material::$replaceable[$next[0]])){
return false;
}
$data["meta"] = (($direction + 3) % 4) & 0x3;
$data2 = $data;
$data2["meta"] = $data2["meta"] | 0x08;
$data2["x"] = $next[2][0];
$data2["y"] = $next[2][1];
$data2["z"] = $next[2][2];
$this->server->handle("player.block.place", $data2);
break;
case 65: //Ladder
if(isset(Material::$transparent[$target[0]])){
return false;
}
$faces = array(
2 => 2,
3 => 3,
4 => 4,
5 => 5,
);
if(!isset($faces[$data["face"]])){
return false;
}
$data["meta"] = $faces[$data["face"]];
break;
case 59://Seeds
case 105:
$blockDown = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
if($blockDown[0] !== 60){
return false;
}
$data["meta"] = 0;
break;
case 81: //Cactus
$blockDown = $this->server->api->level->getBlock($data["x"], $data["y"] - 1, $data["z"]);
$block0 = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"] + 1);
$block1 = $this->server->api->level->getBlock($data["x"], $data["y"], $data["z"] - 1);
$block2 = $this->server->api->level->getBlock($data["x"] + 1, $data["y"], $data["z"]);
$block3 = $this->server->api->level->getBlock($data["x"] - 1, $data["y"], $data["z"]);
if($blockDown[0] !== 12 or !isset(Material::$transparent[$block0[0]]) or !isset(Material::$transparent[$block1[0]]) or !isset(Material::$transparent[$block2[0]]) or !isset(Material::$transparent[$block3[0]])){
return false;
}
break;
if($item->isPlaceable()){
$hand = $item->getBlock();
}else{
return $this->cancelAction($block, $player);
}
$this->server->handle("player.block.place", $data);
if(!($block->isReplaceable === true or ($hand->getID() === SLAB and $block->getID() === SLAB))){
return $this->cancelAction($block, $player);
}
if($hand->isTransparent === false and $player->entity->inBlock($block->x, $block->y, $block->z)){
return $this->cancelAction($block, $player); //Entity in block
}
if($this->server->api->dhandle("player.block.place", array("player" => $player, "block" => $block, "target" => $target, "item" => $item)) === false){
return $this->cancelAction($block, $player);
}elseif($hand->place($this, $item, $player, $block, $target, $face, $fx, $fy, $fz) === false){
return $this->cancelAction($block, $player);
}
if($hand->getID() === SIGN_POST or $hand->getID() === WALL_POST){
$t = $this->server->api->tileentity->addSign($block->x, $block->y, $block->z);
$t->data["creator"] = $player->username;
}
if($this->server->gamemode === SURVIVAL or $this->server->gamemode === ADVENTURE){
$player->removeItem($item->getID(), $item->getMetadata(), 1);
}
return false;
}
@ -602,6 +325,7 @@ class BlockAPI{
return;
}
$this->updateBlock($data["x"], $data["y"], $data["z"], isset($data["type"]) ? $data["type"]:BLOCK_UPDATE_RANDOM);
return true;
}
public function flowLavaOn($source, $face){
@ -627,6 +351,15 @@ class BlockAPI{
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], $spread[0], $level | $down, false);
return true;
}
}elseif($spread[0] === 9 or $spread[0] === 8){
if($source[0] === 11){
$this->server->api->level->setBlock($source[2][0], $source[2][1], $source[2][2], 49, 0);
}elseif($face === 0){
$this->server->api->level->setBlock($source[2][0], $source[2][1], $source[2][2], 1, 0);
}else{
$this->server->api->level->setBlock($source[2][0], $source[2][1], $source[2][2], 4, 0);
}
return true;
}elseif(isset(Material::$flowable[$spread[0]])){
$this->server->schedule(20, array($this, "blockScheduler"), array(
"x" => $spread[2][0],
@ -643,7 +376,7 @@ class BlockAPI{
return false;
}
public function flowWaterOn($source, $face){
public function flowWaterOn($source, $face, &$spread = null){
$down = 0;
if($face === BlockFace::BOTTOM){
$level = 0;
@ -666,6 +399,14 @@ class BlockAPI{
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], $spread[0], $level | $down, false);
return true;
}
}elseif($spread[0] === 11){
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], 49, 0, true);
return true;
}elseif($spread[0] === 10){
if($face === 0 or ($spread[1] & 0x08) === 0){
$this->server->api->level->setBlock($spread[2][0], $spread[2][1], $spread[2][2], 4, 0, true);
return true;
}
}elseif(isset(Material::$flowable[$spread[0]])){
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $spread[2][0],
@ -689,13 +430,34 @@ class BlockAPI{
switch($block[0]){
case 8:
case 9:
if(!$this->flowWaterOn($block, 0) or $block[0] === 9){
$this->flowWaterOn($block, 2);
$this->flowWaterOn($block, 3);
$this->flowWaterOn($block, 4);
$this->flowWaterOn($block, 5);
$faces = array();
if(!$this->flowWaterOn($block, 0, $floor) or $block[0] === 9){
$this->flowWaterOn($block, 2, $faces[0]);
$this->flowWaterOn($block, 3, $faces[1]);
$this->flowWaterOn($block, 4, $faces[2]);
$this->flowWaterOn($block, 5, $faces[3]);
}
if($block[0] === 8){
//Source creation
if(!isset(Material::$flowable[$floor[0]])){
$sources = 0;
foreach($faces as $i => $b){
if($b[0] === 9){
++$sources;
}
}
if($sources >= 2){
$this->server->api->level->setBlock($block[2][0], $block[2][1], $block[2][2], 9, 0, false);
$this->server->schedule(10, array($this, "blockScheduler"), array(
"x" => $block[2][0],
"y" => $block[2][1],
"z" => $block[2][2],
"type" => BLOCK_UPDATE_NORMAL,
));
break;
}
}
$drained = true;
$level = $block[1] & 0x07;
$up = $this->server->api->level->getBlockFace($block, BlockFace::UP);

View File

@ -37,15 +37,23 @@ class ChatAPI{
public function broadcast($message){
$this->send(false, $message);
console("[CHAT] ".$message);
}
public function sendTo($owner, $text, $player){
$this->send($owner, $text, array($player));
}
public function send($owner, $text, $whitelist = false, $blacklist = false){
$message = "";
if($owner !== false){
$message = "<".$owner."> ";
if($owner instanceof Player){
$message = "<".$owner->username."> ";
}else{
$message = "<".$owner."> ";
}
}
$message .= $text;
console("[CHAT] ".$message);
$this->server->handle("server.chat", new Container($message, $whitelist, $blacklist));
}
}

View File

@ -26,10 +26,11 @@ the Free Software Foundation, either version 3 of the License, or
*/
class ConsoleAPI{
private $loop, $server, $event, $help, $cmds;
private $loop, $server, $event, $help, $cmds, $alias;
function __construct(PocketMinecraftServer $server){
$this->help = array();
$this->cmds = array();
$this->alias = array();
$this->server = $server;
$this->last = microtime(true);
}
@ -47,102 +48,103 @@ class ConsoleAPI{
$this->loop->join();
}
public function defaultCommands($cmd, $params){
switch($cmd){
case "crash": //Crashes the server to generate an report
$this->callNotDefinedMethodCrash();
$this->server->api->server; //Access a private property
callNotExistingFunction();
break;
case "invisible":
$p = strtolower(array_shift($params));
switch($p){
case "on":
case "true":
case "1":
console("[INFO] Server is invisible");
$this->server->api->setProperty("invisible", true);
break;
case "off":
case "false":
case "0":
console("[INFO] Server is visible");
$this->server->api->setProperty("invisible", false);
break;
default:
console("[INFO] Usage: /invisible <on | off>");
break;
}
break;
case "status":
case "lag":
$info = $this->server->debugInfo();
console("[INFO] TPS: ".$info["tps"].", Memory usage: ".$info["memory_usage"]." (Peak ".$info["memory_peak_usage"].")");
break;
case "update-done":
$this->server->api->setProperty("last-update", time());
break;
case "stop":
$this->loop->stop = true;
console("[INFO] Stopping the server...");
$this->server->close();
break;
case "gamemode":
$s = trim(array_shift($params));
if($s == "" or (((int) $s) !== 0 and ((int) $s) !== 1)){
console("[INFO] Usage: /gamemode <0 | 1>");
public function defaultCommands($cmd, $params, $issuer, $alias){
$output = "";
switch($cmd){
case "crash": //Crashes the server to generate an report
$this->callNotDefinedMethodCrash();
$this->server->api->server; //Access a private property
callNotExistingFunction();
break;
}
$this->server->api->setProperty("gamemode", (int) $s);
console("[INFO] Gamemode changed to ".$this->server->gamemode);
break;
case "difficulty":
$s = trim(array_shift($params));
if($s == "" or (((int) $s) !== 0 and ((int) $s) !== 1)){
console("[INFO] Usage: /difficulty <0 | 1>");
case "invisible":
$p = strtolower(array_shift($params));
switch($p){
case "on":
case "true":
case "1":
$output .= "Server is invisible\n";
$this->server->api->setProperty("invisible", true);
break;
case "off":
case "false":
case "0":
$output .= "Server is visible\n";
$this->server->api->setProperty("invisible", false);
break;
default:
$output .= "Usage: /invisible <on | off>\n";
break;
}
break;
}
$this->server->api->setProperty("difficulty", (int) $s);
console("[INFO] Difficulty changed to ".$this->server->difficulty);
loadConfig(true);
break;
case "say":
$s = implode(" ", $params);
if(trim($s) == ""){
console("[INFO] Usage: /say <message>");
case "status":
case "lag":
if(!($issuer instanceof Player) and $issuer === "console"){
$this->server->debugInfo(true);
}
$info = $this->server->debugInfo();
$output .= "TPS: ".$info["tps"].", Memory usage: ".$info["memory_usage"]." (Peak ".$info["memory_peak_usage"].")\n";
break;
}
$this->server->api->chat->broadcast($s);
break;
case "save-all":
$this->server->save();
break;
case "help":
case "?":
console("[INFO] /help: Show available commands");
console("[INFO] /status: Show server TPS and memory usage");
console("[INFO] /gamemode: Changes default gamemode");
console("[INFO] /difficulty: Changes difficulty");
console("[INFO] /invisible: Manages server visibility");
console("[INFO] /say: Broadcasts mesages");
console("[INFO] /save-all: Saves pending changes");
console("[INFO] /stop: Stops the server");
//console("[INFO] /restart: Restarts the server");
foreach($this->help as $c => $h){
console("[INFO] /$c: ".$h);
}
break;
default:
console("[ERROR] Command doesn't exist! Use /help");
break;
}
case "update-done":
$this->server->api->setProperty("last-update", time());
break;
case "stop":
$this->loop->stop = true;
$output .= "Stopping the server\n";
$this->server->close();
break;
case "gamemode":
$s = trim(array_shift($params));
if($s == "" or (((int) $s) !== 0 and ((int) $s) !== 1 and ((int) $s) !== 2)){
$output .= "Usage: /gamemode <0 | 1 | 2>\n";
break;
}
$this->server->api->setProperty("gamemode", (int) $s);
$output .= "Gamemode changed to ".$this->server->getGamemode()."\n";
break;
case "difficulty":
$s = trim(array_shift($params));
if($s == "" or (((int) $s) !== 0 and ((int) $s) !== 1)){
$output .= "Usage: /difficulty <0 | 1>\n";
break;
}
$this->server->api->setProperty("difficulty", (int) $s);
$output .= "Difficulty changed to ".$this->server->difficulty."\n";
loadConfig(true);
break;
case "say":
$s = implode(" ", $params);
if(trim($s) == ""){
$output .= "Usage: /say <message>\n";
break;
}
$this->server->api->chat->broadcast($s);
break;
case "save-all":
$this->server->save();
break;
case "help":
case "?":
$output .= "/help: Show available commands\n";
$output .= "/status: Show server TPS and memory usage\n";
$output .= "/gamemode: Changes default gamemode\n";
$output .= "/difficulty: Changes difficulty\n";
$output .= "/invisible: Manages server visibility\n";
$output .= "/say: Broadcasts mesages\n";
$output .= "/save-all: Saves pending changes\n";
$output .= "/stop: Stops the server\n";
foreach($this->help as $c => $h){
$output .= "/$c: ".$h."\n";
}
break;
default:
$output .= "Command doesn't exist! Use /help\n";
break;
}
return $output;
}
public function alias($alias, $cmd){
if(!isset($this->cmds[$cmd])){
return false;
}
$this->cmds[strtolower(trim($alias))] = &$this->cmds[$cmd];
$this->alias[strtolower(trim($alias))] = trim($cmd);
return true;
}
@ -155,15 +157,37 @@ class ConsoleAPI{
$this->help[$cmd] = $help;
}
public function run($line = ""){
public function run($line = "", $issuer = false, $alias = false){
if($line != ""){
$params = explode(" ", $line);
$cmd = strtolower(array_shift($params));
console("[INFO] Issued server command: /$cmd ".implode(" ", $params));
if(isset($this->cmds[$cmd]) and is_callable($this->cmds[$cmd])){
call_user_func($this->cmds[$cmd], $cmd, $params);
}elseif($this->server->api->dhandle("api.console.command", array("cmd" => $cmd, "params" => $params)) !== false){
$this->defaultCommands($cmd, $params);
if(isset($this->alias[$cmd])){
$this->run($this->alias[$cmd] . " " .implode(" ", $params), $issuer, $cmd);
return;
}
if($issuer instanceof Player){
console("[INFO] \"".$issuer->username."\" issued server command: $alias /$cmd ".implode(" ", $params));
}else{
console("[INFO] Issued server command: $alias /$cmd ".implode(" ", $params));
}
if($this->server->api->dhandle("console.command.".$cmd, array("cmd" => $cmd, "parameters" => $params, "issuer" => $issuer, "alias" => $alias)) === false
or $this->server->api->dhandle("console.command", array("cmd" => $cmd, "parameters" => $params, "issuer" => $issuer, "alias" => $alias)) === false){
$output = "You don't have permissions\n";
}else{
if(isset($this->cmds[$cmd]) and is_callable($this->cmds[$cmd])){
$output = @call_user_func($this->cmds[$cmd], $cmd, $params, $issuer, $alias);
}elseif($this->server->api->dhandle("console.command.unknown", array("cmd" => $cmd, "params" => $params, "issuer" => $issuer, "alias" => $alias)) !== false){
$output = $this->defaultCommands($cmd, $params, $issuer, $alias);
}
}
if($output != "" and ($issuer instanceof Player)){
$issuer->sendChat(trim($output));
}elseif($output != "" and $issuer === "console"){
$mes = explode("\n", trim($output));
foreach($mes as $m){
console("[CMD] ".$m);
}
}
}
}
@ -172,7 +196,7 @@ class ConsoleAPI{
if($this->loop->line !== false){
$line = trim($this->loop->line);
$this->loop->line = false;
$this->run($line);
$this->run($line, "console");
}else{
$this->loop->notify();
}

View File

@ -50,12 +50,12 @@ class EntityAPI{
$this->harm($eid, -$heal, $cause);
}
public function harm($eid, $attack = 1, $cause){
public function harm($eid, $attack = 1, $cause, $force = false){
$e = $this->get($eid);
if($e === false or $e->dead === true){
return false;
}
$e->setHealth($e->getHealth() - $attack, $cause);
$e->setHealth($e->getHealth() - $attack, $cause, $force);
}
public function add($class, $type = 0, $data = array()){
@ -94,9 +94,12 @@ class EntityAPI{
public function remove($eid){
if(isset($this->server->entities[$eid])){
$entity = $this->server->entities[$eid];
$this->server->entities[$eid] = null;
unset($this->server->entities[$eid]);
$entity->closed = true;
$this->server->query("DELETE FROM entities WHERE EID = ".$entity->eid.";");
$this->server->api->dhandle("entity.remove", $entity);
$entity = null;
unset($entity);
}
}

View File

@ -34,26 +34,11 @@ class LevelAPI{
}
public function init(){
$this->server->event("player.block.break", array($this, "handle"));
$this->server->event("player.block.place", array($this, "handle"));
$this->server->event("player.block.update", array($this, "handle"));
}
public function handle($data, $event){
switch($event){
case "player.block.place":
case "player.block.update":
console("[DEBUG] EID ".$data["eid"]." placed ".$data["block"].":".$data["meta"]." at X ".$data["x"]." Y ".$data["y"]." Z ".$data["z"], true, true, 2);
$this->setBlock($data["x"], $data["y"], $data["z"], $data["block"], $data["meta"]);
break;
case "player.block.break":
$block = $this->getBlock($data["x"], $data["y"], $data["z"]);
console("[DEBUG] EID ".$data["eid"]." broke ".$block[0].":".$block[1]." at X ".$data["x"]." Y ".$data["y"]." Z ".$data["z"], true, true, 2);
if($block[0] === 0){
break;
}
$this->setBlock($data["x"], $data["y"], $data["z"], 0, 0);
break;
}
}
@ -84,12 +69,10 @@ class LevelAPI{
return $this->heightMap[$z][$x];
}
public function setBlock($x, $y, $z, $block, $meta = 0, $update = true){
public function setBlock($x, $y, $z, $block, $meta = 0, $update = true, $tiles = false){
if($x < 0 or $y < 0 or $z < 0){
return false;
}
$this->map->setBlock($x, $y, $z, $block, $meta);
$this->heightMap[$z][$x] = $this->map->getFloor($x, $z);
if($this->server->api->dhandle("block.change", array(
"x" => $x,
"y" => $y,
@ -97,17 +80,23 @@ class LevelAPI{
"block" => $block,
"meta" => $meta,
)) !== false){
$this->map->setBlock($x, $y, $z, $block, $meta);
$this->heightMap[$z][$x] = $this->map->getFloor($x, $z);
if($update === true){
$this->server->api->block->updateBlock($x, $y, $z, BLOCK_UPDATE_NORMAL);
$this->server->api->block->updateBlocksAround($x, $y, $z, BLOCK_UPDATE_NORMAL);
}
if($tiles === true){
if(($t = $this->server->api->tileentity->get($x, $y, $z)) !== false){
$t[0]->close();
}
}
}
return true;
}
public function getOrderedChunk($X, $Z, $columnsPerPacket = 2){
public function getOrderedChunks($X, $Z, $columnsPerPacket = 2){
$columnsPerPacket = max(1, (int) $columnsPerPacket);
$c = $this->getChunk($X, $Z);
$ordered = array();
$i = 0;
$cnt = 0;
@ -131,4 +120,26 @@ class LevelAPI{
}
return $ordered;
}
public function getMiniChunk($X, $Z, $Y, $MTU){
$ordered = array();
$i = 0;
$ordered[$i] = "";
$cnt = 0;
for($z = 0; $z < 16; ++$z){
for($x = 0; $x < 16; ++$x){
if((strlen($ordered[$i]) + 16 + 8 + 1) > $MTU){
++$i;
$ordered[$i] = str_repeat("\x00", $cnt);
}
$ordered[$i] .= chr(1 << $Y);
$block = $this->map->getChunkColumn($X, $Z, $x, $z, 0);
$meta = $this->map->getChunkColumn($X, $Z, $x, $z, 1);
$ordered[$i] .= substr($block, $Y << 4, 16);
$ordered[$i] .= substr($meta, $Y << 3, 8);
++$cnt;
}
}
return $ordered;
}
}

View File

@ -36,6 +36,7 @@ class PlayerAPI{
$this->server->addHandler("player.death", array($this, "handle"), 1);
$this->server->api->console->register("list", "Shows connected player list", array($this, "commandHandler"));
$this->server->api->console->register("kill", "Kills a player", array($this, "commandHandler"));
$this->server->api->console->register("harm", "Harms a player", array($this, "commandHandler"));
$this->server->api->console->register("tppos", "Teleports a player to a position", array($this, "commandHandler"));
$this->server->api->console->register("tp", "Teleports a player to another player", array($this, "commandHandler"));
}
@ -43,13 +44,17 @@ class PlayerAPI{
public function handle($data, $event){
switch($event){
case "server.regeneration":
$result = $this->server->query("SELECT EID FROM players WHERE EID = (SELECT EID FROM entities WHERE health < 20);");
$result = $this->server->query("SELECT EID FROM entities WHERE class = ".ENTITY_PLAYER." AND health < 20;");
if($result !== true and $result !== false){
while(false !== ($player = $result->fetchArray())){
if(($player = $this->server->api->player->getByEID($player["EID"])) !== false){
$player->entity->setHealth(min(20, $player->entity->getHealth() + $data), "regeneration");
while(($player = $result->fetchArray()) !== false){
if(($player = $this->server->api->entity->get($player["EID"])) !== false){
if($player->getHealth() <= 0){
continue;
}
$player->setHealth(min(20, $player->getHealth() + $data), "regeneration");
}
}
return true;
}
break;
case "player.death":
@ -66,29 +71,58 @@ class PlayerAPI{
}
}else{
switch($data["cause"]){
case "cactus":
$message .= " was pricked to death";
break;
case "lava":
$message .= " tried to swim in lava";
break;
case "fire":
$message .= " went up in flames";
break;
case "burning":
$message .= " burned to death";
break;
case "suffocation":
$message .= " suffocated in a wall";
break;
case "water":
$message .= " drowned";
break;
case "void":
$message .= " fell out of the world";
break;
case "fall":
$message .= " hit the ground too hard";
break;
case "flying":
$message .= " tried to fly up to the sky";
break;
default:
$message .= " was killed";
$message .= " died";
break;
}
}
$this->server->chat(false, $message);
return true;
break;
}
}
public function commandHandler($cmd, $params){
public function commandHandler($cmd, $params, $issuer, $alias){
$output = "";
switch($cmd){
case "tp":
$name = array_shift($params);
$target = array_shift($params);
if($name == null or $target == null){
console("[INFO] Usage: /tp <player> <target>");
$output .= "Usage: /tp <player> <target>\n";
break;
}
if($this->teleport($name, $target)){
console("[INFO] \"$name\" teleported to \"$target\"");
$output .= "\"$name\" teleported to \"$target\"\n";
}else{
console("[ERROR] Couldn't teleport");
$output .= "Couldn't teleport\n";
}
break;
case "tppos":
@ -97,35 +131,45 @@ class PlayerAPI{
$x = array_pop($params);
$name = implode(" ", $params);
if($name == null or $x === null or $y === null or $z === null){
console("[INFO] Usage: /tp <player> <x> <y> <z>");
$output .= "Usage: /tp <player> <x> <y> <z>\n";
break;
}
if($this->tppos($name, $x, $y, $z)){
console("[INFO] \"$name\" teleported to ($x, $y, $z)");
$output .= "\"$name\" teleported to ($x, $y, $z)\n";
}else{
console("[ERROR] Couldn't teleport");
$output .= "Couldn't teleport\n";
}
break;
case "kill":
$player = $this->get(implode(" ", $params));
if($player !== false){
$this->server->api->entity->harm($player->eid, 20, "console");
$this->server->api->entity->harm($player->eid, 20, "console", true);
}else{
console("[INFO] Usage: /kill <player>");
$output .= "Usage: /kill <player>\n";
}
break;
case "harm":
$dmg = (int) array_shift($params);
$player = $this->get(implode(" ", $params));
if($player !== false){
$this->server->api->entity->harm($player->eid, $dmg, "console", true);
}else{
$output .= "Usage: /harm <damage> <player>\n";
}
break;
case "list":
console("[INFO] Player list:");
$output .= "Player list:\n";
foreach($this->server->clients as $c){
console("[INFO] ".$c->username." (".$c->ip.":".$c->port."), ClientID ".$c->clientID.", (".round($c->entity->x, 2).", ".round($c->entity->y, 2).", ".round($c->entity->z, 2).")");
$output .= $c->username." (".$c->ip.":".$c->port."), ClientID ".$c->clientID.", (".round($c->entity->x, 2).", ".round($c->entity->y, 2).", ".round($c->entity->z, 2).")\n";
}
break;
}
return $output;
}
public function teleport($name, $target){
$target = $this->get($target);
if($target !== false){
if(($target instanceof Player) and ($target->entity instanceof Entity)){
return $this->tppos($name, $target->entity->x, $target->entity->y, $target->entity->z);
}
return false;
@ -133,7 +177,10 @@ class PlayerAPI{
public function tppos($name, $x, $y, $z){
$player = $this->get($name);
if($player !== false){
if(($player instanceof Player) and ($player->entity instanceof Entity)){
$player->entity->setPosition($x, $y, $z, 0, 0);
$player->fallY = false;
$player->fallStart = false;
$player->dataPacket(MC_MOVE_PLAYER, array(
"eid" => 0,
"x" => $x,
@ -142,13 +189,15 @@ class PlayerAPI{
"yaw" => 0,
"pitch" => 0,
));
$player->fallY = false;
$player->fallStart = false;
return true;
}
return false;
}
public function get($name){
$CID = $this->server->query("SELECT ip,port FROM players WHERE name = '".str_replace("'", "", $name)."';", true);
$CID = $this->server->query("SELECT ip,port FROM players WHERE name = '".$name."';", true);
$CID = $this->server->clientID($CID["ip"], $CID["port"]);
if(isset($this->server->clients[$CID])){
return $this->server->clients[$CID];
@ -202,17 +251,23 @@ class PlayerAPI{
public function remove($CID){
if(isset($this->server->clients[$CID])){
$player = $this->server->clients[$CID];
$this->server->clients[$CID] = null;
unset($this->server->clients[$CID]);
$player->close();
$this->saveOffline($player->username, $player->data);
$this->server->query("DELETE FROM players WHERE name = '".$player->username."';");
if($player->entity instanceof Entity){
$player->entity->player = null;
$player->entity = null;
}
$this->server->api->entity->remove($player->eid);
$player = null;
unset($player);
}
}
public function getOffline($name){
if(!file_exists(FILE_PATH."players/".$name.".dat")){
if(!file_exists(DATA_PATH."players/".$name.".dat")){
console("[NOTICE] Player data not found for \"".$name."\", creating new profile");
$data = array(
"spawn" => array(
@ -220,14 +275,18 @@ class PlayerAPI{
"y" => $this->server->spawn["y"],
"z" => $this->server->spawn["z"],
),
"inventory" => array_fill(0, 36, array(0, 0, 0)),
"inventory" => array_fill(0, 36, array(AIR, 0, 0)),
"armor" => array_fill(0, 4, array(AIR, 0, 0)),
"health" => 20,
"lastIP" => "",
"lastID" => 0,
);
$this->saveOffline($name, $data);
}else{
$data = unserialize(file_get_contents(FILE_PATH."players/".$name.".dat"));
$data = unserialize(file_get_contents(DATA_PATH."players/".$name.".dat"));
}
if($this->server->gamemode === 1){
$data["health"] = 20;
}
$this->server->handle("api.player.offline.get", $data);
return $data;
@ -235,6 +294,6 @@ class PlayerAPI{
public function saveOffline($name, $data){
$this->server->handle("api.player.offline.save", $data);
file_put_contents(FILE_PATH."players/".str_replace("/", "", $name).".dat", serialize($data));
file_put_contents(DATA_PATH."players/".str_replace("/", "", $name).".dat", serialize($data));
}
}

View File

@ -41,6 +41,7 @@ class PluginAPI extends stdClass{
}
public function getInfo($className){
$className = strtolower($className);
if(!isset($this->plugins[$className])){
return false;
}
@ -49,45 +50,58 @@ class PluginAPI extends stdClass{
}
public function load($file){
$content = file_get_contents($file);
$info = strstr($content, "*/", true);
$content = substr(strstr($content, "*/"),2);
if(preg_match_all('#([a-zA-Z0-9\-_]*)=([^\r\n]*)#u', $info, $matches) == 0){ //false or 0 matches
console("[ERROR] [PluginAPI] Failed parsing of ".basename($file));
return false;
}
$info = array();
foreach($matches[1] as $k => $i){
$v = $matches[2][$k];
switch(strtolower($v)){
case "on":
case "true":
case "yes":
$v = true;
break;
case "off":
case "false":
case "no":
$v = false;
break;
if(strtolower(substr($file, -3)) === "pmf"){
$pmf = new PMFPlugin($file);
$info = $pmf->getPluginInfo();
}else{
$content = file_get_contents($file);
$info = strstr($content, "*/", true);
$content = substr(strstr($content, "*/"),2);
if(preg_match_all('#([a-zA-Z0-9\-_]*)=([^\r\n]*)#u', $info, $matches) == 0){ //false or 0 matches
console("[ERROR] [PluginAPI] Failed parsing of ".basename($file));
return false;
}
$info[$i] = $v;
$info = array();
foreach($matches[1] as $k => $i){
$v = $matches[2][$k];
switch(strtolower($v)){
case "on":
case "true":
case "yes":
$v = true;
break;
case "off":
case "false":
case "no":
$v = false;
break;
}
$info[$i] = $v;
}
$info["code"] = $content;
$info["class"] = trim(strtolower($info["class"]));
}
if(!isset($info["name"]) or !isset($info["version"]) or !isset($info["class"]) or !isset($info["author"])){
console("[ERROR] [PluginAPI] Failed parsing of ".basename($file));
return false;
}
console("[INFO] [PluginAPI] Loading plugin \"\x1b[32m".$info["name"]."\x1b[0m\" \x1b[35m".$info["version"]."\x1b[0m by \x1b[36m".$info["author"]."\x1b[0m");
console("[INFO] [PluginAPI] Loading plugin \"\x1b[32m".$info["name"]."\x1b[0m\" \x1b[35m".$info["version"]." #".intval($info["apiversion"])."\x1b[0m by \x1b[36m".$info["author"]."\x1b[0m");
if(class_exists($info["class"])){
console("[ERROR] [PluginAPI] Failed loading plugin: class exists");
return false;
}
if(eval($content) === false or !class_exists($info["class"])){
if(eval($info["code"]) === false or !class_exists($info["class"])){
console("[ERROR] [PluginAPI] Failed loading plugin: evaluation error");
return false;
}
$className = trim($info["class"]);
if(isset($info["api"]) and $info["api"] !== true){
console("[NOTICE] [PluginAPI] Plugin \"\x1b[36m".$info["name"]."\x1b[0m\" got raw access to Server methods");
$className = $info["class"];
if(isset($info["apiversion"]) and intval($info["apiversion"]) > CURRENT_API_VERSION){
console("[ERROR] [PluginAPI] Plugin \"".$info["name"]."\" uses a newer API! It can crash or corrupt the server!");
}elseif(!isset($info["apiversion"]) or intval($info["apiversion"]) < CURRENT_API_VERSION){
console("[NOTICE] [PluginAPI] Plugin \"".$info["name"]."\" uses an old API");
}
$object = new $className($this->server->api, ((isset($info["api"]) and $info["api"] !== true) ? $this->server:false));
$object = new $className($this->server->api, false);
if(!($object instanceof Plugin)){
console("[ERROR] [PluginAPI] Plugin \"\x1b[36m".$info["name"]."\x1b[0m\" doesn't use the Plugin Interface");
if(method_exists($object, "__destruct")){
@ -114,7 +128,7 @@ class PluginAPI extends stdClass{
if($p === false){
return false;
}
$path = FILE_PATH."plugins/".$p[1]["name"]."/";
$path = DATA_PATH."plugins/".$p[1]["name"]."/";
$this->plugins[$p[1]["class"]][1]["path"] = $path;
return $path;
}
@ -124,7 +138,8 @@ class PluginAPI extends stdClass{
if($p === false){
return false;
}
$path = FILE_PATH."plugins/".$p[1]["name"]."/";
$path = DATA_PATH."plugins/".$p[1]["name"]."/";
@mkdir($path);
$this->plugins[$p[1]["class"]][1]["path"] = $path;
$cnf = new Config($path."config.yml", CONFIG_YAML, $default);
$cnf->save();
@ -159,11 +174,12 @@ class PluginAPI extends stdClass{
public function loadAll(){
console("[INFO] Loading Plugins...");
$dir = dir(FILE_PATH."plugins/");
$dir = dir(DATA_PATH."plugins/");
while(false !== ($file = $dir->read())){
if($file{0} !== "."){
if(strtolower(substr($file, -3)) === "php"){
$this->load(FILE_PATH."plugins/" . $file);
$ext = strtolower(substr($file, -3));
if($ext === "php" or $ext === "pmf"){
$this->load(DATA_PATH."plugins/" . $file);
}
}
}

View File

@ -27,23 +27,28 @@ the Free Software Foundation, either version 3 of the License, or
class ServerAPI{
var $restart = false;
private static $serverRequest = false;
private $server;
private $config;
private $apiList = array();
public static function request(){
return self::$serverRequest;
}
public function run(){
$this->load();
return $this->init();
}
public function load(){
@mkdir(FILE_PATH."logs/", 0777, true);
@mkdir(FILE_PATH."players/", 0777);
@mkdir(FILE_PATH."worlds/", 0777);
@mkdir(FILE_PATH."plugins/", 0777);
@mkdir(DATA_PATH."logs/", 0777, true);
@mkdir(DATA_PATH."players/", 0777);
@mkdir(DATA_PATH."worlds/", 0777);
@mkdir(DATA_PATH."plugins/", 0777);
console("[INFO] Starting ServerAPI server handler...");
file_put_contents(FILE_PATH."logs/packets.log", "");
if(!file_exists(FILE_PATH."logs/test.bin.log") or md5_file(FILE_PATH."logs/test.bin.log") !== TEST_MD5){
file_put_contents(DATA_PATH."logs/packets.log", "");
if(!file_exists(DATA_PATH."logs/test.bin.log") or md5_file(DATA_PATH."logs/test.bin.log") !== TEST_MD5){
console("[NOTICE] Executing tests...");
console("[INFO] OS: ".PHP_OS.", ".Utils::getOS());
console("[INFO] uname -a: ".php_uname("a"));
@ -59,19 +64,17 @@ class ServerAPI{
$test .= Utils::writeInt(Utils::readInt("\xff\xff\xff\xff"));
$test .= Utils::writeInt(1);
$test .= Utils::writeInt(-1);
$test .= Utils::writeFloat(Utils::readfloat("\xff\xff\xff\xff"));
$test .= Utils::writeFloat(Utils::readFloat("\xff\xff\xff\xff"));
$test .= Utils::writeFloat(-1.584563155838E+29);
$test .= Utils::writeFloat(1);
$test .= Utils::writeLDouble(Utils::readLDouble("\xff\xff\xff\xff\xff\xff\xff\xff"));
$test .= Utils::writeLong("-1152921504606846977");
$test .= Utils::writeLong("-1152921504606846976");
$test .= Utils::writeTriad(16777215);
$test .= Utils::writeTriad(16777216);
$str = new Java_String("TESTING\x00\n\r\t\xff");
$test .= Utils::writeLong($str->hashCode());
$test .= Utils::writeInt($str->hashCode());
$test .= Utils::writeDataArray(array("a", "b", "c", "\xff\xff\xff\xff"));
$test .= Utils::hexToStr("012334567890");
file_put_contents(FILE_PATH."logs/test.bin.log", $test);
file_put_contents(DATA_PATH."logs/test.bin.log", $test);
$md5 = md5($test);
console("[INFO] MD5 of test: ".$md5);
if($md5 !== TEST_MD5){
@ -81,17 +84,17 @@ class ServerAPI{
}
console("[DEBUG] Loading server.properties...", true, true, 2);
$this->config = new Config(FILE_PATH . "server.properties", CONFIG_PROPERTIES, array(
$this->config = new Config(DATA_PATH . "server.properties", CONFIG_PROPERTIES, array(
"server-name" => "Minecraft Server",
"description" => "Server made using PocketMine-MP",
"motd" => "Welcome @username to this server!",
"invisible" => false,
"server-ip" => "0.0.0.0",
"port" => 19132,
"memory-limit" => "256M",
"last-update" => false,
"update-channel" => "stable",
"white-list" => false,
"debug" => 2,
"debug" => 1,
"max-players" => 20,
"server-type" => "normal",
"time-per-second" => 20,
@ -102,10 +105,12 @@ class ServerAPI{
"level-name" => false,
"server-id" => false,
"upnp-forwarding" => false,
"send-usage" => true,
));
$this->parseProperties();
define("DEBUG", $this->getProperty("debug"));
$this->server = new PocketMinecraftServer($this->getProperty("server-name"), $this->getProperty("gamemode"), false, $this->getProperty("port"), $this->getProperty("server-id"));
$this->server = new PocketMinecraftServer($this->getProperty("server-name"), $this->getProperty("gamemode"), false, $this->getProperty("port"), $this->getProperty("server-id"), $this->getProperty("server-ip"));
self::$serverRequest = $this->server;
$this->setProperty("server-id", $this->server->serverID);
$this->server->api = $this;
if($this->getProperty("upnp-forwarding") === true){
@ -118,23 +123,17 @@ class ServerAPI{
if($this->getProperty("last-update") === false or ($this->getProperty("last-update") + 3600) < time()){
console("[INFO] Checking for new server version");
console("[INFO] Last check: \x1b[36m".date("Y-m-d H:i:s", $this->getProperty("last-update"))."\x1b[0m");
$channel = "stable";
if($this->getProperty("update-channel") == "dev" or $this->getProperty("update-channel") == "development"){
$channel = "dev";
}
$this->setProperty("update-channel", $channel);
if($channel === "dev"){
$info = json_decode(Utils::curl_get("https://api.github.com/repos/shoghicp/PocketMine-MP"), true);
if($info === false or !isset($info["updated_at"])){
console("[ERROR] GitHub API Error");
$info = json_decode(Utils::curl_get("http://www.pocketmine.org/latest"), true);
if($this->server->version->isDev()){
if($info === false or !isset($info["development"])){
console("[ERROR] PocketMine.org API error");
}else{
$last = new DateTime($info["updated_at"]);
$last = $last->getTimestamp();
$last = $info["development"]["date"];
if($last >= $this->getProperty("last-update") and $this->getProperty("last-update") !== false){
console("[NOTICE] \x1b[33mA new DEVELOPMENT version of PocketMine-MP has been released");
console("[NOTICE] \x1b[36mIf you want to update, get the latest version at https://github.com/shoghicp/PocketMine-MP/archive/master.zip");
console("[NOTICE] This message will dissapear when you issue the command \"/update-done\"");
console("[NOTICE] \x1b[33mVersion \"".$info["development"]["version"]."\" [".substr($info["development"]["commit"], 0, 10)."]");
console("[NOTICE] \x1b[36mIf you want to update, get the latest version at ".$info["development"]["download"]);
console("[NOTICE] This message will dissapear after issuing the command \"/update-done\"");
sleep(3);
}else{
$this->setProperty("last-update", time());
@ -142,26 +141,17 @@ class ServerAPI{
}
}
}else{
$info = json_decode(Utils::curl_get("https://api.github.com/repos/shoghicp/PocketMine-MP/tags"), true);
if($info === false or !isset($info[0])){
console("[ERROR] GitHub API Error");
if($info === false or !isset($info["stable"])){
console("[ERROR] PocketMine.org API error");
}else{
$newest = new VersionString(MAJOR_VERSION);
$newest = array(-1, $newest->getNumber());
foreach($info as $i => $tag){
$update = new VersionString($tag["name"]);
$update = $update->getNumber();
if($update > $newest[1]){
$newest = array($i, $update);
}
}
if($newest[0] !== -1){
$target = $info[$newest[0]];
$newestN = $newest->getNumber();
$update = new VersionString($info["stable"]["version"]);
$updateN = $update->getNumber();
if($updateN > $newestN){
console("[NOTICE] \x1b[33mA new STABLE version of PocketMine-MP has been released");
console("[NOTICE] \x1b[36mVersion \"".(new VersionString($newest[1]))."\" #".$newest[1]." [".substr($target["commit"]["sha"], 0, 10)."]");
console("[NOTICE] Download it at ".$target["zipball_url"]);
console("[NOTICE] \x1b[36mVersion \"".$info["stable"]["version"]."\" #".$updateN);
console("[NOTICE] Download it at ".$info["stable"]["download"]);
console("[NOTICE] This message will dissapear as soon as you update");
sleep(5);
}else{
@ -172,17 +162,17 @@ class ServerAPI{
}
}
if(file_exists(FILE_PATH."worlds/level.dat")){
if(file_exists(DATA_PATH."worlds/level.dat")){
console("[NOTICE] Detected unimported map data. Importing...");
$this->importMap(FILE_PATH."worlds/", true);
$this->importMap(DATA_PATH."worlds/", true);
}
$this->server->mapName = $this->getProperty("level-name");
$this->server->mapDir = FILE_PATH."worlds/".$this->server->mapName."/";
$this->server->mapDir = DATA_PATH."worlds/".$this->server->mapName."/";
if($this->server->mapName === false or trim($this->server->mapName) === "" or (!file_exists($this->server->mapDir."chunks.dat") and !file_exists($this->server->mapDir."chunks.dat.gz"))){
if($this->server->mapName === false or trim($this->server->mapName) === ""){
$this->server->mapName = "world";
}
$this->server->mapDir = FILE_PATH."worlds/".$this->server->mapName."/";
$this->server->mapDir = DATA_PATH."worlds/".$this->server->mapName."/";
$generator = "SuperflatGenerator";
if($this->getProperty("generator") !== false and class_exists($this->getProperty("generator"))){
$generator = $this->getProperty("generator");
@ -199,19 +189,19 @@ class ServerAPI{
}
$this->loadProperties();
$this->server->loadMap();
//Autoload all default APIs
console("[INFO] Loading default APIs");
$dir = dir(FILE_PATH."src/API/");
while(false !== ($file = $dir->read())){
if($file{0} !== "."){ //Hidden and upwards folders
$API = basename($file, ".php");
if(strtolower($API) !== "serverapi" and strtolower($API) !== "pluginapi"){
$name = strtolower(substr($API, 0, -3));
$this->loadAPI($name, $API);
}
}
}
$this->loadAPI("console", "ConsoleAPI");
$this->loadAPI("level", "LevelAPI");
$this->loadAPI("block", "BlockAPI");
$this->loadAPI("chat", "ChatAPI");
$this->loadAPI("ban", "BanAPI");
$this->loadAPI("entity", "EntityAPI");
$this->loadAPI("tileentity", "TileEntityAPI");
$this->loadAPI("player", "PlayerAPI");
$this->loadAPI("time", "TimeAPI");
foreach($this->apiList as $ob){
if(is_callable(array($ob, "init"))){
$ob->init(); //Fails sometimes!!!
@ -223,6 +213,18 @@ class ServerAPI{
$this->server->loadEntities();
}
public function sendUsage(){
console("[INTERNAL] Sending usage data...", true, true, 3);
Utils::curl_post("http://www.pocketmine.org/usage.php", array(
"serverid" => $this->server->serverID,
"os" => Utils::getOS(),
"version" => MAJOR_VERSION,
"protocol" => CURRENT_PROTOCOL,
"online" => count($this->server->clients),
"max" => $this->server->maxClients,
));
}
public function __destruct(){
foreach($this->apiList as $ob){
@ -248,7 +250,7 @@ class ServerAPI{
if(!$this->config->exists("invisible")){
$this->config->set("invisible", false);
}
if(is_object($this->server)){
if($this->server instanceof PocketMinecraftServer){
$this->server->setType($this->getProperty("server-type"));
$this->server->timePerSecond = $this->getProperty("time-per-second");
$this->server->invisible = $this->getProperty("invisible");
@ -295,6 +297,10 @@ class ServerAPI{
}
public function init(){
if($this->getProperty("send-usage") !== false){
$this->server->schedule(36000, array($this, "sendUsage"), array(), true); //Send usage data every 30 minutes
$this->sendUsage();
}
$this->server->init();
unregister_tick_function(array($this->server, "tick"));
$this->__destruct();
@ -344,27 +350,30 @@ class ServerAPI{
if(file_exists($dir."level.dat")){
$nbt = new NBT();
$level = parseNBTData($nbt->loadFile($dir."level.dat"));
if($level["LevelName"] == ""){
$level["LevelName"] = "world".time();
}
console("[DEBUG] Importing map \"".$level["LevelName"]."\" gamemode ".$level["GameType"]." with seed ".$level["RandomSeed"], true, true, 2);
unset($level["Player"]);
$lvName = $level["LevelName"]."/";
@mkdir(FILE_PATH."worlds/".$lvName, 0777);
file_put_contents(FILE_PATH."worlds/".$lvName."level.dat", serialize($level));
@mkdir(DATA_PATH."worlds/".$lvName, 0777);
file_put_contents(DATA_PATH."worlds/".$lvName."level.dat", serialize($level));
$entities = parseNBTData($nbt->loadFile($dir."entities.dat"));
file_put_contents(FILE_PATH."worlds/".$lvName."entities.dat", serialize($entities["Entities"]));
file_put_contents(DATA_PATH."worlds/".$lvName."entities.dat", serialize($entities["Entities"]));
if(!isset($entities["TileEntities"])){
$entities["TileEntities"] = array();
}
file_put_contents(FILE_PATH."worlds/".$lvName."tileEntities.dat", serialize($entities["TileEntities"]));
file_put_contents(DATA_PATH."worlds/".$lvName."tileEntities.dat", serialize($entities["TileEntities"]));
console("[DEBUG] Imported ".count($entities["Entities"])." Entities and ".count($entities["TileEntities"])." TileEntities", true, true, 2);
if($remove === true){
rename($dir."chunks.dat", FILE_PATH."worlds/".$lvName."chunks.dat");
rename($dir."chunks.dat", DATA_PATH."worlds/".$lvName."chunks.dat");
unlink($dir."level.dat");
@unlink($dir."level.dat_old");
@unlink($dir."player.dat");
unlink($dir."entities.dat");
}else{
copy($dir."chunks.dat", FILE_PATH."worlds/".$lvName."chunks.dat");
copy($dir."chunks.dat", DATA_PATH."worlds/".$lvName."chunks.dat");
}
if($this->getProperty("level-name") === false){
console("[INFO] Setting default level to \"".$level["LevelName"]."\"");
@ -437,15 +446,19 @@ class ServerAPI{
}
public function loadAPI($name, $class, $dir = false){
if($dir === false){
$dir = FILE_PATH."src/API/";
}
$file = $dir.$class.".php";
if(!file_exists($file)){
console("[ERROR] API ".$name." [".$class."] in ".$dir." doesn't exist", true, true, 0);
if(isset($this->$name)){
return false;
}elseif(!class_exists($class)){
if($dir === false){
$dir = FILE_PATH."src/API/";
}
$file = $dir.$class.".php";
if(!file_exists($file)){
console("[ERROR] API ".$name." [".$class."] in ".$dir." doesn't exist", true, true, 0);
return false;
}
require_once($file);
}
require_once($file);
$this->$name = new $class($this->server);
$this->apiList[] = $this->$name;
console("[INFO] API \x1b[36m".$name."\x1b[0m [\x1b[30;1m".$class."\x1b[0m] loaded");

136
src/API/TileEntityAPI.php Normal file
View File

@ -0,0 +1,136 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class TileEntityAPI{
private $server;
function __construct(PocketMinecraftServer $server){
$this->server = $server;
}
public function get($x, $y = false, $z = false){
if(($x instanceof Vector3) or ($x instanceof Block)){
$z = (int) $x->z;
$y = (int) $x->y;
$x = (int) $x->x;
}else{
$x = (int) $x;
$y = (int) $y;
$z = (int) $z;
}
$tiles = $this->server->query("SELECT * FROM tileentities WHERE x = $x AND y = $y AND z = $z;");
$ret = array();
if($tiles !== false and $tiles !== true){
while(($t = $tiles->fetchArray(SQLITE3_ASSOC)) !== false){
if(($tile = $this->getByID($t["ID"])) !== false){
if($tile->normal === true){
$ret[] = $tile;
}
}
}
}
if(count($ret) === 0){
return false;
}
return $ret;
}
public function getByID($id){
if($id instanceof TileEntity){
return $id;
}elseif(isset($this->server->tileEntities[$id])){
return $this->server->tileEntities[$id];
}
return false;
}
public function init(){
}
public function getAll(){
return $this->server->tileEntities;
}
public function add($class, $x, $y, $z, $data = array()){
$id = $this->tCnt++;
$this->server->tileEntities[$id] = new TileEntity($this->server, $id, $class, $x, $y, $z, $data);
$this->spawnToAll($id);
return $this->server->tileEntities[$id];
}
public function addSign($x, $y, $z, $lines = array("", "", "", "")){
return $this->add(TILE_SIGN, $x, $y, $z, $data = array(
"id" => "Sign",
"x" => $x,
"y" => $y,
"z" => $z,
"Text1" => $lines[0],
"Text2" => $lines[1],
"Text3" => $lines[2],
"Text4" => $lines[3],
));
}
public function spawnTo($id, $player, $queue = false){
$t = $this->getByID($id);
if($t === false){
return false;
}
$t->spawn($player, $queue);
}
public function spawnToAll($id){
$t = $this->getByID($id);
if($t === false){
return false;
}
foreach($this->server->api->player->getAll() as $player){
if($player->eid !== false){
$t->spawn($player);
}
}
}
public function spawnAll($player){
foreach($this->getAll() as $t){
$t->spawn($player);
}
}
public function remove($id){
if(isset($this->server->tileEntities[$id])){
$t = $this->server->tileEntities[$eid];
$this->server->tileEntities[$id] = null;
unset($this->server->tileEntities[$id]);
$t->closed = true;
$t->close();
$this->server->query("DELETE FROM tileentities WHERE ID = ".$id.";");
$t = null;
unset($t);
}
}
}

View File

@ -41,13 +41,14 @@ class TimeAPI{
$this->server->api->console->register("time", "Manages server time", array($this, "commandHandler"));
}
public function commandHandler($cmd, $params){
public function commandHandler($cmd, $params, $issuer, $alias){
$output = "";
switch($cmd){
case "time":
$p = strtolower(array_shift($params));
switch($p){
case "check":
console("[INFO] Time: ".$this->getDate().", ".$this->getPhase()." (".$this->get(true).")");
$output .= "Time: ".$this->getDate().", ".$this->getPhase()." (".$this->get(true).")\n";
break;
case "add":
$this->add(array_shift($params));
@ -68,11 +69,12 @@ class TimeAPI{
$this->night();
break;
default:
console("[INFO] Usage: /time <check | set | add | sunrise | day | sunset | night> [time]");
$output .= "Usage: /time <check | set | add | sunrise | day | sunset | night> [time]\n";
break;
}
break;
}
return $output;
}
public function night(){

View File

@ -110,17 +110,26 @@ class Material{
51 => true,
53 => true,
59 => true,
63 => true,
64 => true,
65 => true,
67 => true,
68 => true,
71 => true,
78 => true,
79 => true,
83 => true,
85 => true,
89 => true,
96 => true,
102 => true,
105 => true,
107 => true,
108 => true,
109 => true,
114 => true,
128 => true,
156 => true,
);
static $replaceable = array(
0 => true,
@ -151,6 +160,7 @@ class Material{
96 => true,
105 => true,
107 => true,
245 => true,
247 => true,
);
static $placeable = array(
@ -225,8 +235,17 @@ class Material{
362 => 105,
107 => true,
108 => true,
109 => true,
112 => true,
114 => true,
128 => true,
155 => true,
156 => true,
245 => true,
246 => true,
247 => true,
323 => true, //Special case of signs
338 => 83,
);
static $blocks = array(
0 => "Air",

View File

@ -29,6 +29,8 @@ the Free Software Foundation, either version 3 of the License, or
class Deprecation{
public static $events = array(
"world.block.change" => "block.change",
"block.drop" => "item.drop",
"api.op.check" => "op.check",
);

1020
src/Player.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -26,8 +26,9 @@ the Free Software Foundation, either version 3 of the License, or
*/
class PocketMinecraftServer{
var $version, $invisible, $api, $tickMeasure, $preparedSQL, $seed, $gamemode, $name, $maxClients, $clients, $eidCnt, $custom, $description, $motd, $timePerSecond, $spawn, $entities, $mapDir, $mapName, $map, $levelData, $tileEntities;
private $database, $interface, $evCnt, $handCnt, $events, $handlers, $serverType, $lastTick, $ticker;
public $tCnt;
public $version, $invisible, $api, $tickMeasure, $preparedSQL, $seed, $gamemode, $name, $maxClients, $clients, $eidCnt, $custom, $description, $motd, $timePerSecond, $spawn, $entities, $mapDir, $mapName, $map, $levelData, $tileEntities;
private $serverip, $database, $interface, $evCnt, $handCnt, $events, $eventsID, $handlers, $serverType, $lastTick, $ticker;
private function load(){
$this->version = new VersionString();
@ -36,19 +37,21 @@ class PocketMinecraftServer{
if($this->version->isDev()){
console("[INFO] \x1b[31;1mThis is a Development version");
}
console("[INFO] Starting Minecraft PE Server at *:".$this->port);
if($this->port < 19132 or $this->port > 19135){
console("[INFO] Starting Minecraft PE Server at ".$this->serverip.":".$this->port);
if($this->port < 19132 or $this->port > 19135){ //Mojang =(
console("[WARNING] You've selected a not-standard port. Normal port range is from 19132 to 19135 included");
}
$this->serverID = $this->serverID === false ? Utils::readLong(Utils::getRandomBytes(8)):$this->serverID;
$this->seed = $this->seed === false ? Utils::readInt(Utils::getRandomBytes(4)):$this->seed;
$this->serverID = $this->serverID === false ? Utils::readLong(Utils::getRandomBytes(8, false)):$this->serverID;
$this->seed = $this->seed === false ? Utils::readInt(Utils::getRandomBytes(4, false)):$this->seed;
console("[INFO] Loading database...");
$this->startDatabase();
$this->doTick = false;
$this->api = false;
$this->api = false;
$this->tCnt = 1;
$this->mapDir = false;
$this->mapName = false;
$this->events = array();
$this->eventsID = array();
$this->handlers = array();
$this->map = false;
$this->invisible = false;
@ -57,12 +60,12 @@ class PocketMinecraftServer{
$this->tileEntities = array();
$this->entities = array();
$this->custom = array();
$this->evCnt = 0;
$this->handCnt = 0;
$this->evCnt = 1;
$this->handCnt = 1;
$this->eidCnt = 1;
$this->maxClients = 20;
$this->schedule = array();
$this->scheduleCnt = 0;
$this->scheduleCnt = 1;
$this->description = "";
$this->whitelist = false;
$this->clients = array();
@ -75,16 +78,17 @@ class PocketMinecraftServer{
$this->reloadConfig();
console("[INFO] Server Name: \x1b[36m".$this->name."\x1b[0m");
console("[DEBUG] Server ID: ".$this->serverID, true, true, 2);
$this->stop = false;
$this->stop = false;
}
function __construct($name, $gamemode = 1, $seed = false, $port = 19132, $serverID = false){
function __construct($name, $gamemode = CREATIVE, $seed = false, $port = 19132, $serverID = false, $serverip = "0.0.0.0"){
$this->port = (int) $port; //19132 - 19135
$this->gamemode = (int) $gamemode;
$this->name = $name;
$this->motd = "Welcome to ".$name;
$this->serverID = $serverID;
$this->seed = $seed;
$this->serverip = $serverip;
$this->load();
}
@ -93,16 +97,24 @@ class PocketMinecraftServer{
$tps = 40 / ($v[39] - $v[0]);
return round($tps, 4);
}
public function titleTick(){
if(ENABLE_ANSI === true){
echo "\x1b]0;PocketMine-MP ".MAJOR_VERSION." | Online ". count($this->clients)." | RAM ".round((memory_get_usage(true) / 1024) / 1024, 2)."MB | TPS ".$this->getTPS()."\x07";
}
}
public function loadEvents(){
if(ENABLE_ANSI === true){
$this->action(1500000, '$this->titleTick();');
}
$this->action(500000, '$this->time += (int) ($this->timePerSecond / 2);$this->api->dhandle("server.time", $this->time);');
$this->action(5000000, 'if($this->difficulty < 2){$this->api->dhandle("server.regeneration", 1);}');
$this->action(1000000 * 60, '$this->reloadConfig();');
$this->action(1000000 * 60 * 10, '$this->custom = array();');
if($this->api !== false){
if($this->api instanceof ServerAPI){
$this->action(1000000 * 80, '$cnt = count($this->clients); if($cnt > 1){$this->api->chat->broadcast("Online (".$cnt."): ".implode(", ",$this->api->player->online()));}');
}
$this->action(1000000 * 120, '$this->debugInfo(true);');
}
public function startDatabase(){
@ -111,15 +123,13 @@ class PocketMinecraftServer{
//$this->query("PRAGMA journal_mode = OFF;");
//$this->query("PRAGMA encoding = \"UTF-8\";");
//$this->query("PRAGMA secure_delete = OFF;");
$this->query("CREATE TABLE players (clientID INTEGER PRIMARY KEY, EID NUMERIC, ip TEXT, port NUMERIC, name TEXT UNIQUE);");
$this->query("CREATE TABLE players (clientID INTEGER PRIMARY KEY, EID NUMERIC, ip TEXT, port NUMERIC, name TEXT UNIQUE COLLATE NOCASE);");
$this->query("CREATE TABLE entities (EID INTEGER PRIMARY KEY, type NUMERIC, class NUMERIC, name TEXT, x NUMERIC, y NUMERIC, z NUMERIC, yaw NUMERIC, pitch NUMERIC, health NUMERIC);");
$this->query("CREATE TABLE metadata (EID INTEGER PRIMARY KEY, name TEXT, value TEXT);");
$this->query("CREATE TABLE tileentities (ID INTEGER PRIMARY KEY, class TEXT, x NUMERIC, y NUMERIC, z NUMERIC, spawnable NUMERIC);");
$this->query("CREATE TABLE actions (ID INTEGER PRIMARY KEY, interval NUMERIC, last NUMERIC, code TEXT, repeat NUMERIC);");
$this->query("CREATE TABLE events (ID INTEGER PRIMARY KEY, name TEXT);");
$this->query("CREATE TABLE handlers (ID INTEGER PRIMARY KEY, name TEXT, priority NUMERIC);");
//$this->query("PRAGMA synchronous = OFF;");
$this->preparedSQL->selectHandlers = $this->database->prepare("SELECT DISTINCT ID FROM handlers WHERE name = :name ORDER BY priority DESC;");
$this->preparedSQL->selectEvents = $this->database->prepare("SELECT DISTINCT ID FROM events WHERE name = :name;");
$this->preparedSQL->selectActions = $this->database->prepare("SELECT ID,code,repeat FROM actions WHERE last <= (:time - interval);");
$this->preparedSQL->updateActions = $this->database->prepare("UPDATE actions SET last = :time WHERE last <= (:time - interval);");
}
@ -144,8 +154,7 @@ class PocketMinecraftServer{
$info["memory_peak_usage"] = round((memory_get_peak_usage(true) / 1024) / 1024, 2)."MB";
$info["entities"] = $this->query("SELECT count(EID) as count FROM entities;", true);
$info["entities"] = $info["entities"]["count"];
$info["events"] = $this->query("SELECT count(ID) as count FROM events;", true);
$info["events"] = $info["events"]["count"];
$info["events"] = count($this->eventsID);
$info["handlers"] = $this->query("SELECT count(ID) as count FROM handlers;", true);
$info["handlers"] = $info["handlers"]["count"];
$info["actions"] = $this->query("SELECT count(ID) as count FROM actions;", true);
@ -192,7 +201,7 @@ class PocketMinecraftServer{
}
public function addHandler($event, $callable, $priority = 5){
public function addHandler($event,callable $callable, $priority = 5){
if(!is_callable($callable)){
return false;
}elseif(isset(Deprecation::$events[$event])){
@ -215,7 +224,7 @@ class PocketMinecraftServer{
$this->preparedSQL->selectHandlers->clear();
$this->preparedSQL->selectHandlers->bindValue(":name", $event, SQLITE3_TEXT);
$handlers = $this->preparedSQL->selectHandlers->execute();
$result = true;
$result = null;
if($handlers !== false and $handlers !== true){
console("[INTERNAL] Handling ".$event, true, true, 3);
$call = array();
@ -224,7 +233,7 @@ class PocketMinecraftServer{
}
$handlers->finalize();
foreach($call as $hnid => $boolean){
if($result !== false){
if($result !== false and $result !== true){
$called[$hnid] = true;
$handler = $this->handlers[$hnid];
if(is_array($handler)){
@ -244,7 +253,7 @@ class PocketMinecraftServer{
}
console("[ERROR] Event \"$event\" has been deprecated.$sub [Handler]");
}
if($result !== false){
$this->trigger($event, $data);
}
@ -278,7 +287,7 @@ class PocketMinecraftServer{
console("[INFO] Spawn: X \x1b[36m".$this->levelData["SpawnX"]."\x1b[0m Y \x1b[36m".$this->levelData["SpawnY"]."\x1b[0m Z \x1b[36m".$this->levelData["SpawnZ"]."\x1b[0m");
console("[INFO] Time: \x1b[36m".$this->time."\x1b[0m");
console("[INFO] Seed: \x1b[36m".$this->seed."\x1b[0m");
console("[INFO] Gamemode: \x1b[36m".($this->gamemode === 0 ? "survival":"creative")."\x1b[0m");
console("[INFO] Gamemode: \x1b[36m".$this->getGamemode()."\x1b[0m");
$d = array(0 => "peaceful", 1 => "easy", 2 => "normal", 3 => "hard");
console("[INFO] Difficulty: \x1b[36m".$d[$this->difficulty]."\x1b[0m");
console("[INFO] Loading map...");
@ -292,7 +301,18 @@ class PocketMinecraftServer{
}else{
console("[INFO] Time: \x1b[36m".$this->time."\x1b[0m");
console("[INFO] Seed: \x1b[36m".$this->seed."\x1b[0m");
console("[INFO] Gamemode: \x1b[36m".($this->gamemode === 0 ? "survival":"creative")."\x1b[0m");
console("[INFO] Gamemode: \x1b[36m".$this->getGamemode()."\x1b[0m");
}
}
public function getGamemode(){
switch($this->gamemode){
case SURVIVAL:
return "survival";
case CREATIVE:
return "creative";
case ADVENTURE:
return "adventure";
}
}
@ -319,16 +339,25 @@ class PocketMinecraftServer{
"yaw" => $entity["Rotation"][0],
"pitch" => $entity["Rotation"][1],
));
}else{
$e = $this->api->entity->add(ENTITY_MOB, $entity["id"]);
}elseif($entity["id"] === OBJECT_PAINTING){ //Painting
$e = $this->api->entity->add(ENTITY_OBJECT, $entity["id"], $entity);
$e->setPosition($entity["Pos"][0], $entity["Pos"][1], $entity["Pos"][2], $entity["Rotation"][0], $entity["Rotation"][1]);
$e->setHealth($entity["Health"]);
}else{
$e = $this->api->entity->add(ENTITY_MOB, $entity["id"], $entity);
$e->setPosition($entity["Pos"][0], $entity["Pos"][1], $entity["Pos"][2], $entity["Rotation"][0], $entity["Rotation"][1]);
$e->setHealth($entity["Health"]);
}
}
}
console("[DEBUG] Loaded ".count($this->entities)." Entities", true, true, 2);
$this->action(1000000 * 60 * 15, '$this->api->chat->broadcast("Forcing save...");$this->save();');
$tiles = unserialize(file_get_contents($this->mapDir."tileEntities.dat"));
foreach($tiles as $tile){
if(!isset($tile["id"])){
break;
}
$t = $this->api->tileentity->add($tile["id"], $tile["x"], $tile["y"], $tile["z"], $tile);
}
$this->action(1000000 * 60 * 25, '$this->api->chat->broadcast("Forcing save...");$this->save();');
}
}
@ -337,11 +366,75 @@ class PocketMinecraftServer{
$this->levelData["Time"] = $this->time;
file_put_contents($this->mapDir."level.dat", serialize($this->levelData));
$this->map->saveMap($final);
console("[INFO] Saving entities...");
foreach($this->entities as $entity){
}
$this->trigger("server.save", $final);
console("[INFO] Saving entities...");
if(count($this->entities) > 0){
$entities = array();
foreach($this->entities as $entity){
if($entity->class === ENTITY_MOB){
$entities[] = array(
"id" => $entity->type,
"Color" => @$entity->data["Color"],
"Sheared" => @$entity->data["Sheared"],
"Health" => $entity->health,
"Pos" => array(
0 => $entity->x,
1 => $entity->y,
2 => $entity->z,
),
"Rotation" => array(
0 => $entity->yaw,
1 => $entity->pitch,
),
);
}elseif($entity->class === ENTITY_OBJECT){
$entities[] = array(
"id" => $entity->type,
"TileX" => $entity->x,
"TileX" => $entity->y,
"TileX" => $entity->z,
"Health" => $entity->health,
"Motive" => $entity->data["Motive"],
"Pos" => array(
0 => $entity->x,
1 => $entity->y,
2 => $entity->z,
),
"Rotation" => array(
0 => $entity->yaw,
1 => $entity->pitch,
),
);
}elseif($entity->class === ENTITY_ITEM){
$entities[] = array(
"id" => 64,
"Item" => array(
"id" => $entity->type,
"Damage" => $entity->meta,
"Count" => $entity->stack,
),
"Health" => $entity->health,
"Pos" => array(
0 => $entity->x,
1 => $entity->y,
2 => $entity->z,
),
"Rotation" => array(
0 => 0,
1 => 0,
),
);
}
}
file_put_contents($this->mapDir."entities.dat", serialize($entities));
}
if(count($this->tileEntities) > 0){
$tiles = array();
foreach($this->tileEntities as $tile){
$tiles[] = $tile->data;
}
file_put_contents($this->mapDir."tileEntities.dat", serialize($tiles));
}
}
}
@ -367,11 +460,18 @@ class PocketMinecraftServer{
console("[INFO] Server started!");
$this->process();
}
public function dumpError(){
console("[ERROR] An Unrecovereable has ocurred and the server has Crashed. Creating an Error Dump");
$dump = "# PocketMine-MP Error Dump ".date("D M j H:i:s T Y")."\r\n";
$dump .= "Error: ".var_export(error_get_last(), true)."\r\n\r\n";
$er = error_get_last();
$dump .= "Error: ".var_export($er, true)."\r\n\r\n";
$dump .= "Code: \r\n";
$file = file($er["file"], FILE_IGNORE_NEW_LINES);
for($l = max(0, $er["line"] - 10); $l < $er["line"] + 10; ++$l){
$dump .= "[".($l + 1)."] ".$file[$l]."\r\n";
}
$dump .= "\r\n\r\n";
$version = new VersionString();
$dump .= "PM Version: ".$version." #".$version->getNumber()." [Protocol ".CURRENT_PROTOCOL."]\r\n";
$dump .= "uname -a: ".php_uname("a")."\r\n";
@ -382,8 +482,9 @@ class PocketMinecraftServer{
global $arguments;
$dump .= "Parameters: ".var_export($arguments, true)."\r\n\r\n\r\n";
$dump .= "server.properties: ".var_export($this->api->getProperties(), true)."\r\n\r\n\r\n";
global $lasttrace;
$dump .= "Last Backtrace: ".$lasttrace."\r\n\r\n\r\n";
if($this->api->plugin instanceof PluginAPI){
$dump .= "Loaded plugins: ".var_export($this->api->plugin->getList(), true)."\r\n\r\n\r\n";
}
$dump .= "Loaded Modules: ".var_export(get_loaded_extensions(), true)."\r\n\r\n";
$name = "error_dump_".time();
logg($dump, $name, true, 0, true);
@ -446,14 +547,16 @@ class PocketMinecraftServer{
$this->custom["times_".$CID] = 0;
}
$ln = 15;
$this->description .= " ";
if($this->description == "" or substr($this->description, -1) != " "){
$this->description .= " ";
}
$txt = substr($this->description, $this->custom["times_".$CID], $ln);
$txt .= substr($this->description, 0, $ln - strlen($txt));
$this->send(0x1c, array(
$data[0],
$this->serverID,
MAGIC,
$this->serverType. $this->name . " [".($this->gamemode === 1 ? "C":"S").($this->whitelist !== false ? "W":"")." ".count($this->clients)."/".$this->maxClients."] ".$txt,
$this->serverType. $this->name . " [".($this->gamemode === CREATIVE ? "C":($this->gamemode === ADVENTURE ? "A":"S")).($this->whitelist !== false ? "W":"")." ".count($this->clients)."/".$this->maxClients."] ".$txt,
), false, $packet["ip"], $packet["port"]);
$this->custom["times_".$CID] = ($this->custom["times_".$CID] + 1) % strlen($this->description);
break;
@ -478,9 +581,10 @@ class PocketMinecraftServer{
}
$version = $data[1];
$size = strlen($data[2]);
if($version !== CURRENT_PROTOCOL){
if($version !== CURRENT_STRUCTURE){
console("[DEBUG] Incorrect structure #$version from ".$packet["ip"].":".$packet["port"], true, true, 2);
$this->send(0x1a, array(
CURRENT_PROTOCOL,
CURRENT_STRUCTURE,
MAGIC,
$this->serverID,
), false, $packet["ip"], $packet["port"]);
@ -538,21 +642,8 @@ class PocketMinecraftServer{
}
public function trigger($event, $data = ""){
$this->preparedSQL->selectEvents->reset();
$this->preparedSQL->selectEvents->clear();
$this->preparedSQL->selectEvents->bindValue(":name", $event, SQLITE3_TEXT);
$events = $this->preparedSQL->selectEvents->execute();
if($events === false or $events === true){
return;
}
$call = array();
while(($evn = $events->fetchArray(SQLITE3_ASSOC)) !== false){
$call[(int) $evn["ID"]] = true;
}
$events->finalize();
if(count($call) > 0){
foreach($call as $evid => $boolean){
$ev = $this->events[$evid];
if(isset($this->events[$event])){
foreach($this->events[$event] as $evid => $ev){
if(!is_callable($ev)){
$this->deleteEvent($evid);
continue;
@ -571,25 +662,23 @@ class PocketMinecraftServer{
}
console("[ERROR] Event \"$event\" has been deprecated.$sub [Trigger]");
}
return true;
}
public function schedule($ticks, $callback, $data = array(), $repeat = false, $eventName = "server.schedule"){
public function schedule($ticks,callable $callback, $data = array(), $repeat = false, $eventName = "server.schedule"){
if(!is_callable($callback)){
return false;
}
$add = "";
$chcnt = $this->scheduleCnt++;
if($repeat === false){
$add = ' unset($this->schedule['.$chcnt.']);';
$add = '$this->schedule['.$chcnt.']=null;unset($this->schedule['.$chcnt.']);';
}
$this->schedule[$chcnt] = array($callback, $data, $eventName);
$this->action(50000 * $ticks, '$schedule = $this->schedule['.$chcnt.'];'.$add.'if(!is_callable($schedule[0])){unset($this->schedule['.$chcnt.']);return false;} call_user_func($schedule[0], $schedule[1], $schedule[2]);', (bool) $repeat);
$this->action(50000 * $ticks, '$schedule=$this->schedule['.$chcnt.'];'.$add.'if(!is_callable($schedule[0])){$this->schedule['.$chcnt.']=null;unset($this->schedule['.$chcnt.']);return false;}return call_user_func($schedule[0],$schedule[1],$schedule[2]);', (bool) $repeat);
return $chcnt;
}
public function action($microseconds, $code, $repeat = true){
public function action($microseconds, $code, $repeat = true){
$this->query("INSERT INTO actions (interval, last, code, repeat) VALUES(".($microseconds / 1000000).", ".microtime(true).", '".base64_encode($code)."', ".($repeat === true ? 1:0).");");
console("[INTERNAL] Attached to action ".$microseconds, true, true, 3);
}
@ -617,7 +706,7 @@ class PocketMinecraftServer{
$this->preparedSQL->updateActions->execute();
}
public function event($event, $func){
public function event($event,callable $func){
if(!is_callable($func)){
return false;
}elseif(isset(Deprecation::$events[$event])){
@ -628,16 +717,27 @@ class PocketMinecraftServer{
console("[ERROR] Event \"$event\" has been deprecated.$sub [Attach to ".(is_array($func) ? get_class($func[0])."::".$func[1]:$func)."]");
}
$evid = $this->evCnt++;
$this->events[$evid] = $func;
$this->query("INSERT INTO events (ID, name) VALUES (".$evid.", '".str_replace("'", "\\'", $event)."');");
if(!isset($this->events[$event])){
$this->events[$event] = array();
}
$this->events[$event][$evid] = $func;
$this->eventsID[$evid] = $event;
console("[INTERNAL] Attached ".(is_array($func) ? get_class($func[0])."::".$func[1]:$func)." to event ".$event." (ID ".$evid.")", true, true, 3);
return $evid;
}
public function deleteEvent($id){
$id = (int) $id;
unset($this->events[$id]);
$this->query("DELETE FROM events WHERE ID = ".$id.";");
if(isset($this->eventsID[$id])){
$ev = $this->eventsID[$id];
$this->eventsID[$id] = null;
unset($this->eventsID[$id]);
$this->events[$ev][$id] = null;
unset($this->events[$ev][$id]);
if(count($this->events[$ev]) === 0){
unset($this->events[$ev]);
}
}
}
}

View File

@ -1,565 +0,0 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class Player{
private $server;
private $queue = array();
private $buffer = array();
private $evid = array();
var $timeout;
var $connected = true;
var $clientID;
var $ip;
var $port;
var $counter = array(0, 0, 0);
var $username;
var $eid = false;
var $data = array();
var $entity = false;
var $auth = false;
var $CID;
var $MTU;
var $spawned = false;
var $inventory;
var $equipment = array(1, 0);
var $loggedIn = false;
function __construct(PocketMinecraftServer $server, $clientID, $ip, $port, $MTU){
$this->MTU = $MTU;
$this->server = $server;
$this->clientID = $clientID;
$this->CID = $this->server->clientID($ip, $port);
$this->ip = $ip;
$this->port = $port;
$this->timeout = microtime(true) + 25;
$this->inventory = array_fill(0, 36, array(0, 0, 0));
$this->evid[] = $this->server->event("server.tick", array($this, "onTick"));
$this->evid[] = $this->server->event("server.close", array($this, "close"));
console("[DEBUG] New Session started with ".$ip.":".$port.". MTU ".$this->MTU.", Client ID ".$this->clientID, true, true, 2);
}
public function onTick($time, $event){
if($event !== "server.tick"){ //WTF??
return;
}
if($time > $this->timeout){
$this->close("timeout");
}else{
if(!empty($this->queue)){
$cnt = 0;
while($cnt < 4){
$p = array_shift($this->queue);
if($p === null){
break;
}
switch($p[0]){
case 0:
$this->dataPacket($p[1], $p[2], false, $p[3]);
break;
case 1:
eval($p[1]);
break;
}
++$cnt;
}
}
}
}
public function save(){
if(is_object($this->entity)){
$this->data["spawn"] = array(
"x" => $this->entity->x,
"y" => $this->entity->y,
"z" => $this->entity->z,
);
}
}
public function close($reason = "", $msg = true){
if($this->connected === true){
foreach($this->evid as $ev){
$this->server->deleteEvent($ev);
}
$this->server->api->dhandle("player.quit", $this);
$reason = $reason == "" ? "server stop":$reason;
$this->save();
$this->eventHandler(new Container("You have been kicked. Reason: ".$reason), "server.chat");
$this->dataPacket(MC_LOGIN_STATUS, array(
"status" => 1,
));
$this->dataPacket(MC_DISCONNECT);
$this->connected = false;
if($msg === true){
$this->server->api->chat->broadcast($this->username." left the game");
}
console("[INFO] Session with \x1b[36m".$this->ip.":".$this->port."\x1b[0m Client ID ".$this->clientID." closed due to ".$reason);
$this->server->api->player->remove($this->CID);
}
}
public function addItem($type, $damage, $count){
while($count > 0){
$add = 0;
foreach($this->inventory as $s => $data){
if($data[0] === 0){
$add = min(64, $count);
$this->inventory[$s] = array($type, $damage, $add);
break;
}elseif($data[0] === $type and $data[1] === $damage){
$add = min(64 - $data[2], $count);
if($add <= 0){
continue;
}
$this->inventory[$s] = array($type, $damage, $data[2] + $add);
break;
}
}
if($add === 0){
return false;
}
$count -= $add;
}
return true;
}
public function removeItem($type, $damage, $count){
while($count > 0){
$remove = 0;
foreach($this->inventory as $s => $data){
if($data[0] === $type and $data[1] === $damage){
$remove = min($count, $data[2]);
if($remove < $data[2]){
$this->inventory[$s][2] -= $remove;
}else{
$this->inventory[$s] = array(0, 0, 0);
}
break;
}
}
if($remove === 0){
return false;
}
$count -= $remove;
}
return true;
}
public function hasItem($type, $damage = false){
foreach($this->inventory as $s => $data){
if($data[0] === $type and ($data[1] === $damage or $damage === false) and $data[2] > 0){
return true;
}
}
return false;
}
public function eventHandler($data, $event){
switch($event){
case "player.block.place":
if($data["eid"] === $this->eid and $this->server->gamemode === 0){
$this->removeItem($data["original"][0], $data["original"][1], 1);
}
break;
case "player.pickup":
if($data["eid"] === $this->eid){
$data["eid"] = 0;
if($this->server->gamemode === 0){
$this->addItem($data["entity"]->type, $data["entity"]->meta, $data["entity"]->stack);
}
}
$this->dataPacket(MC_TAKE_ITEM_ENTITY, $data);
break;
case "player.equipment.change":
if($data["eid"] === $this->eid){
break;
}
$this->dataPacket(MC_PLAYER_EQUIPMENT, $data);
break;
case "block.change":
$this->dataPacket(MC_UPDATE_BLOCK, $data);
break;
case "entity.move":
if($data->eid === $this->eid){
break;
}
$this->dataPacket(MC_MOVE_ENTITY_POSROT, array(
"eid" => $data->eid,
"x" => $data->x,
"y" => $data->y,
"z" => $data->z,
"yaw" => $data->yaw,
"pitch" => $data->pitch,
));
break;
case "entity.remove":
if($data->eid === $this->eid){
break;
}
$this->dataPacket(MC_REMOVE_ENTITY, array(
"eid" => $data->eid,
));
break;
case "server.time":
$this->dataPacket(MC_SET_TIME, array(
"time" => $data,
));
break;
case "entity.animate":
if($data["eid"] === $this->eid){
break;
}
$this->dataPacket(MC_ANIMATE, array(
"eid" => $data["eid"],
"action" => $data["action"],
));
break;
case "server.chat":
if(($data instanceof Container) === true){
if(!$data->check($this->username)){
return;
}else{
$message = $data->get();
}
}else{
$message = (string) $data;
}
$this->dataPacket(MC_CHAT, array(
"message" => str_replace("@username", $this->username, $message),
));
break;
}
}
public function handle($pid, $data){
if($this->connected === true){
$this->timeout = microtime(true) + 25;
switch($pid){
case 0xa0: //NACK
if(isset($this->buffer[$data[2]])){
array_unshift($this->queue, array(0, $this->buffer[$data[2]][0], $this->buffer[$data[2]][1], $data[2]));
}
if(isset($data[3])){
if(isset($this->buffer[$data[3]])){
array_unshift($this->queue, array(0, $this->buffer[$data[3]][0], $this->buffer[$data[3]][1], $data[3]));
}
}
break;
case 0xc0: //ACK
$diff = $data[2] - $this->counter[2];
if($diff > 8){ //Packet recovery
array_unshift($this->queue, array(0, $this->buffer[$data[2]][0], $this->buffer[$data[2]][1], $data[2]));
}
$this->counter[2] = $data[2];
unset($this->buffer[$data[2]]);
if(isset($data[3])){
$diff = $data[3] - $this->counter[2];
if($diff > 8){ //Packet recovery
array_unshift($this->queue, array(0, $this->buffer[$data[3]][0], $this->buffer[$data[3]][1], $data[3]));
}
$this->counter[2] = $data[3];
unset($this->buffer[$data[3]]);
}
break;
case 0x07:
$this->send(0x08, array(
MAGIC,
$this->server->serverID,
$this->port,
$data[3],
0,
));
break;
case 0x80:
case 0x81:
case 0x82:
case 0x83:
case 0x84:
case 0x85:
case 0x86:
case 0x87:
case 0x88:
case 0x89:
case 0x8a:
case 0x8b:
case 0x8c:
case 0x8d:
case 0x8e:
case 0x8f:
if(isset($data[0])){
$diff = $data[0] - $this->counter[1];
if($diff > 1){ //Packet recovery
for($i = $this->counter[1]; $i < $data[0]; ++$i){
$this->send(0xa0, array(1, true, $i));
}
$this->counter[1] = $data[0];
}elseif($diff === 1){
$this->counter[1] = $data[0];
}
$this->send(0xc0, array(1, true, $data[0]));
}
switch($data["id"]){
case MC_KEEP_ALIVE:
break;
case 0x03:
break;
case MC_DISCONNECT:
$this->close("client disconnect");
break;
case MC_CLIENT_CONNECT:
$this->dataPacket(MC_SERVER_HANDSHAKE, array(
"port" => $this->port,
"session" => $data["session"],
"session2" => Utils::readLong("\x00\x00\x00\x00\x04\x44\x0b\xa9"),
));
break;
case MC_CLIENT_HANDSHAKE:
break;
case MC_LOGIN:
if($this->loggedIn === true){
break;
}
$this->loggedIn = true;
$this->username = str_replace(array("\x00", "/", " ", "\r", "\n"), array("", "-", "_", "", ""), $data["username"]);
if($this->username == ""){
$this->close("bad username", false);
break;
}
$o = $this->server->api->player->getOffline($this->username);
if($this->server->whitelist === true and !$this->server->api->ban->inWhitelist($this->username)){
$this->close("\"\x1b[33m".$this->username."\x1b[0m\" not being on white-list", false);
break;
}elseif($this->server->api->ban->isBanned($this->username) or $this->server->api->ban->isIPBanned($this->ip)){
$this->close("\"\x1b[33m".$this->username."\x1b[0m\" is banned!", false);
}
$u = $this->server->api->player->get($this->username);
$c = $this->server->api->player->getByClientID($this->clientID);
if($u !== false){
$u->close("logged in from another location");
}
if($c !== false){
$c->close("logged in from another location");
}
if($this->server->api->dhandle("player.join", $this) === false){
$this->close();
return;
}
$this->server->api->player->add($this->CID);
$this->auth = true;
if(!isset($this->data["inventory"]) or $this->server->gamemode === 1){
$this->data["inventory"] = $this->inventory;
}
$this->inventory = &$this->data["inventory"];
$this->data["lastIP"] = $this->ip;
$this->data["lastID"] = $this->clientID;
$this->server->api->player->saveOffline($this->username, $this->data);
$this->dataPacket(MC_LOGIN_STATUS, array(
"status" => 0,
));
$this->dataPacket(MC_START_GAME, array(
"seed" => $this->server->seed,
"x" => $this->data["spawn"]["x"],
"y" => $this->data["spawn"]["y"],
"z" => $this->data["spawn"]["z"],
"unknown1" => 0,
"gamemode" => $this->server->gamemode,
"eid" => 0,
));
break;
case MC_READY:
switch($data["status"]){
case 1:
if($this->spawned !== false){
break;
}
$this->spawned = true;
$this->entity = $this->server->api->entity->add(ENTITY_PLAYER, 0, array("player" => $this));
$this->eid = $this->entity->eid;
$this->server->query("UPDATE players SET EID = ".$this->eid." WHERE clientID = ".$this->clientID.";");
$this->entity->x = $this->data["spawn"]["x"];
$this->entity->y = $this->data["spawn"]["y"];
$this->entity->z = $this->data["spawn"]["z"];
$this->entity->setName($this->username);
$this->entity->data["clientID"] = $this->clientID;
$this->server->api->entity->spawnAll($this);
$this->server->api->entity->spawnToAll($this->eid);
$this->evid[] = $this->server->event("server.time", array($this, "eventHandler"));
$this->evid[] = $this->server->event("server.chat", array($this, "eventHandler"));
$this->evid[] = $this->server->event("entity.remove", array($this, "eventHandler"));
$this->evid[] = $this->server->event("entity.move", array($this, "eventHandler"));
$this->evid[] = $this->server->event("entity.animate", array($this, "eventHandler"));
$this->evid[] = $this->server->event("player.equipment.change", array($this, "eventHandler"));
$this->evid[] = $this->server->event("player.pickup", array($this, "eventHandler"));
$this->evid[] = $this->server->event("block.change", array($this, "eventHandler"));
$this->evid[] = $this->server->event("player.block.place", array($this, "eventHandler"));
console("[DEBUG] Player \"".$this->username."\" EID ".$this->eid." spawned at X ".$this->entity->x." Y ".$this->entity->y." Z ".$this->entity->z, true, true, 2);
$this->eventHandler(new Container($this->server->motd), "server.chat");
if($this->MTU <= 548){
$this->eventHandler("Your connection is bad, you may experience lag and slow map loading.", "server.chat");
}
foreach($this->inventory as $s => $data){
if($data[0] <= 0 or $data[2] <= 0){
$this->inventory[$s] = array(0, 0, 0);
continue;
}
$e = $this->server->api->entity->add(ENTITY_ITEM, $data[0], array(
"x" => $this->entity->x + 0.5,
"y" => $this->entity->y + 0.19,
"z" => $this->entity->z + 0.5,
"meta" => $data[1],
"stack" => $data[2],
));
$this->server->api->entity->spawnTo($e->eid, $this);
}
break;
case 2://Chunk loaded?
break;
}
break;
case MC_MOVE_PLAYER:
if(is_object($this->entity)){
$this->entity->setPosition($data["x"], $data["y"], $data["z"], $data["yaw"], $data["pitch"]);
$this->server->api->dhandle("player.move", $this->entity);
}
break;
case MC_PLAYER_EQUIPMENT:
$data["eid"] = $this->eid;
if($this->server->handle("player.equipment.change", $data) !== false){
$this->equipment[0] = $data["block"];
$this->equipment[1] = $data["meta"];
console("[DEBUG] EID ".$this->eid." has now ".$data["block"].":".$data["meta"]." in their hands!", true, true, 2);
}
break;
case MC_REQUEST_CHUNK:
$this->actionQueue('
$max = max(1, floor(($this->MTU - 16 - 255) / 192));
$chunk = $this->server->api->level->getOrderedChunk('.$data["x"].', '.$data["z"].', $max);
foreach($chunk as $d){
$this->dataPacket(MC_CHUNK_DATA, array(
"x" => '.$data["x"].',
"z" => '.$data["z"].',
"data" => $d,
), true);
}
');
console("[INTERNAL] Chunk X ".$data["x"]." Z ".$data["z"]." requested", true, true, 3);
break;
case MC_USE_ITEM:
$data["eid"] = $this->eid;
if(Utils::distance($this->entity->position, $data) > 10){
break;
}elseif($this->server->gamemode === 0 and !$this->hasItem($data["block"], $data["meta"])){
console("[DEBUG] Player \"".$this->username."\" tried to place not got block (or crafted block)", true, true, 2);
//break;
}
$this->server->handle("player.block.action", $data);
break;
case MC_REMOVE_BLOCK:
$data["eid"] = $this->eid;
if(Utils::distance($this->entity->position, $data) > 8){
break;
}
$this->server->handle("player.block.break", $data);
break;
case MC_INTERACT:
if(isset($this->server->entities[$data["target"]]) and Utils::distance($this->entity->position, $this->server->entities[$data["target"]]->position) <= 8){
if($this->handle("player.interact", $data) !== false){
console("[DEBUG] EID ".$this->eid." attacked EID ".$data["target"], true, true, 2);
if($this->server->gamemode !== 1 and $this->server->difficulty > 0){
$this->server->api->entity->harm($data["target"], $this->server->difficulty, $this->eid);
}
}
}
break;
case MC_ANIMATE:
$this->server->api->dhandle("entity.animate", array("eid" => $this->eid, "action" => $data["action"]));
break;
case MC_RESPAWN:
$this->entity->invincible = true;
$this->entity->setHealth(20, "respawn");
$this->entity->setPosition($data["x"], $data["y"], $data["z"], 0, 0);
$this->entity->invincible = false;
break;
case MC_SET_HEALTH:
if($this->server->gamemode === 1){
break;
}
//$this->entity->setHealth($data["health"], "client");
break;
case MC_DROP_ITEM:
if($this->server->handle("player.drop", $data) !== false){
$this->server->api->block->drop($this->entity->x, $this->entity->y, $this->entity->z, $data["block"], $data["meta"], $data["stack"]);
}
break;
default:
console("[DEBUG] Unhandled 0x".dechex($data["id"])." Data Packet for Client ID ".$this->clientID.": ".print_r($data, true), true, true, 2);
break;
}
break;
}
}
}
public function send($pid, $data = array(), $raw = false){
if($this->connected === true){
$this->server->send($pid, $data, $raw, $this->ip, $this->port);
}
}
public function actionQueue($code){
$this->queue[] = array(1, $code);
}
public function dataPacket($id, $data = array(), $queue = false, $count = false){
if($queue === true){
$this->queue[] = array(0, $id, $data, $count);
}else{
if($count === false){
$count = $this->counter[0];
++$this->counter[0];
if(count($this->buffer) >= 512){
array_shift($this->buffer);
}
$this->buffer[$count] = array($id, $data);
}
$data["id"] = $id;
$this->send(0x80, array(
$count,
0x00,
$data,
));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,284 +0,0 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
define("ENTITY_PLAYER", 0);
define("ENTITY_MOB", 1);
define("ENTITY_OBJECT", 2);
define("ENTITY_ITEM", 3);
define("ENTITY_PAINTING", 4);
class Entity extends stdClass{
var $invincible = false, $eid, $type, $name, $x, $y, $z, $speedX, $speedY, $speedZ, $speed, $last = array(0, 0, 0, 0), $yaw, $pitch, $dead, $data, $class, $attach, $metadata, $closed, $player, $onTick;
private $server;
function __construct($server, $eid, $class, $type = 0, $data = array()){
$this->server = $server;
$this->eid = (int) $eid;
$this->type = (int) $type;
$this->class = (int) $class;
$this->player = false;
$this->attach = false;
$this->data = $data;
$this->status = 0;
$this->health = 20;
$this->dead = false;
$this->closed = false;
$this->name = "";
$this->server->query("INSERT OR REPLACE INTO entities (EID, type, class, health) VALUES (".$this->eid.", ".$this->type.", ".$this->class.", ".$this->health.");");
$this->server->schedule(4, array($this, "update"), array(), true);
$this->metadata = array();
$this->x = isset($this->data["x"]) ? $this->data["x"]:0;
$this->y = isset($this->data["y"]) ? $this->data["y"]:0;
$this->z = isset($this->data["z"]) ? $this->data["z"]:0;
$this->speedX = isset($this->data["speedX"]) ? $this->data["speedX"]:0;
$this->speedY = isset($this->data["speedY"]) ? $this->data["speedY"]:0;
$this->speedZ = isset($this->data["speedZ"]) ? $this->data["speedZ"]:0;
$this->speed = 0;
$this->yaw = isset($this->data["yaw"]) ? $this->data["yaw"]:0;
$this->pitch = isset($this->data["pitch"]) ? $this->data["pitch"]:0;
$this->position = array("x" => &$this->x, "y" => &$this->y, "z" => &$this->z, "yaw" => &$this->yaw, "pitch" => &$this->pitch);
switch($this->class){
case ENTITY_PLAYER:
$this->player = $this->data["player"];
$this->health = &$this->player->data["health"];
break;
case ENTITY_ITEM:
$this->meta = (int) $this->data["meta"];
$this->stack = (int) $this->data["stack"];
break;
case ENTITY_MOB:
//$this->setName((isset($mobs[$this->type]) ? $mobs[$this->type]:$this->type));
break;
case ENTITY_OBJECT:
//$this->setName((isset($objects[$this->type]) ? $objects[$this->type]:$this->type));
break;
}
}
public function update(){
$this->calculateVelocity();
$this->server->api->dhandle("entity.move", $this);
if($this->class === ENTITY_ITEM and $this->closed === false and $this->server->gamemode === 0){
$player = $this->server->query("SELECT EID FROM entities WHERE class == ".ENTITY_PLAYER." AND abs(x - {$this->x}) <= 1.5 AND abs(y - {$this->y}) <= 1.5 AND abs(z - {$this->z}) <= 1.5 LIMIT 1;", true);
if($player !== true and $player !== false){
if($this->server->api->dhandle("player.pickup", array(
"eid" => $player["EID"],
"entity" => $this,
"block" => $this->type,
"meta" => $this->meta,
"target" => $this->eid
)) !== false){
$this->close();
}
}
}
}
public function getDirection(){
$rotation = ($this->yaw - 90) % 360;
if ($rotation < 0) {
$rotation += 360.0;
}
if(0 <= $rotation && $rotation < 45) {
return 2;
}elseif(45 <= $rotation && $rotation < 135) {
return 3;
}elseif(135 <= $rotation && $rotation < 225) {
return 0;
}elseif(225 <= $rotation && $rotation < 315) {
return 1;
}elseif(315 <= $rotation && $rotation < 360) {
return 2;
}else{
return null;
}
}
public function spawn($player){
if(!is_object($player)){
$player = $this->server->api->player->get($player);
}
if($player->eid === $this->eid){
return false;
}
switch($this->class){
case ENTITY_PLAYER:
$player->dataPacket(MC_ADD_PLAYER, array(
"clientID" => $this->player->clientID,
"username" => $this->player->username,
"eid" => $this->eid,
"x" => $this->x,
"y" => $this->y,
"z" => $this->z,
));
$player->dataPacket(MC_PLAYER_EQUIPMENT, array(
"eid" => $this->eid,
"block" => $this->player->equipment[0],
"meta" => $this->player->equipment[1],
));
break;
case ENTITY_ITEM:
$player->dataPacket(MC_ADD_ITEM_ENTITY, array(
"eid" => $this->eid,
"x" => $this->x,
"y" => $this->y,
"z" => $this->z,
"block" => $this->type,
"meta" => $this->meta,
"stack" => $this->stack,
));
break;
case ENTITY_MOB:
$player->dataPacket(MC_ADD_MOB, array(
"type" => $this->type,
"eid" => $this->eid,
"x" => $this->x,
"y" => $this->y,
"z" => $this->z,
));
break;
case ENTITY_OBJECT:
//$this->setName((isset($objects[$this->type]) ? $objects[$this->type]:$this->type));
break;
}
}
public function close(){
if($this->closed === false){
$this->server->api->entity->remove($this->eid);
$this->closed = true;
}
}
public function __destruct(){
$this->close();
}
public function getEID(){
return $this->eid;
}
public function getName(){
return $this->name;
}
public function setName($name){
$this->name = $name;
$this->server->query("UPDATE entities SET name = '".str_replace("'", "", $this->name)."' WHERE EID = ".$this->eid.";");
}
public function look($pos2){
$pos = $this->getPosition();
$angle = Utils::angle3D($pos2, $pos);
$this->yaw = $angle["yaw"];
$this->pitch = $angle["pitch"];
$this->server->query("UPDATE entities SET pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
}
public function setCoords($x, $y, $z){
$this->x = $x;
$this->y = $y;
$this->z = $z;
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z." WHERE EID = ".$this->eid.";");
}
public function move($x, $y, $z, $yaw = 0, $pitch = 0){
$this->x += $x;
$this->y += $y;
$this->z += $z;
$this->yaw += $yaw;
$this->yaw %= 360;
$this->pitch += $pitch;
$this->pitch %= 90;
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z.", pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
}
public function setPosition($x, $y, $z, $yaw, $pitch){
$this->x = $x;
$this->y = $y;
$this->z = $z;
$this->yaw = $yaw;
$this->pitch = $pitch;
$this->server->query("UPDATE entities SET x = ".$this->x.", y = ".$this->y.", z = ".$this->z.", pitch = ".$this->pitch.", yaw = ".$this->yaw." WHERE EID = ".$this->eid.";");
}
public function inBlock($x, $y, $z){
$block = new Vector3($x + 0.5, $y, $z + 0.5);
$me = new Vector3($this->x, $this->y, $this->z);
if(($y == ((int) $this->y) or $y == (((int) $this->y) + 1)) and $block->maxPlainDistance($me) < 0.8){
return true;
}
return false;
}
public function calculateVelocity(){
$diffTime = microtime(true) - $this->last[3];
$this->last[3] = microtime(true);
$origin = new Vector3($this->last[0], $this->last[1], $this->last[2]);
$final = new Vector3($this->x, $this->y, $this->z);
$speedX = abs($this->x - $this->last[0]) / $diffTime;
$this->last[0] = $this->x;
$speedY = ($this->y - $this->last[1]) / $diffTime;
$this->last[1] = $this->y;
$speedZ = abs($this->z - $this->last[2]) / $diffTime;
$this->last[2] = $this->z;
$this->speedX = $speedX;
$this->speedY = $speedY;
$this->speedZ = $speedZ;
$this->speed = $origin->distance($final) / $diffTime;
}
public function getPosition($round = false){
return !isset($this->position) ? false:($round === true ? array_map("floor", $this->position):$this->position);
}
public function setHealth($health, $cause = ""){
$this->health = (int) $health;
$this->server->query("UPDATE entities SET health = ".$this->health." WHERE EID = ".$this->eid.";");
$this->server->api->dhandle("entity.health.change", array("eid" => $this->eid, "health" => $health, "cause" => $cause));
if($this->player !== false){
$this->player->dataPacket(MC_SET_HEALTH, array(
"health" => $this->health,
));
}
if($this->health <= 0 and $this->dead === false){
$this->dead = true;
if($this->player !== false){
$this->server->api->dhandle("player.death", array("name" => $this->name, "cause" => $cause));
}
}elseif($this->health > 0){
$this->dead = false;
}
}
public function getHealth(){
return $this->health;
}
}
?>

View File

@ -32,12 +32,20 @@ error_reporting(E_ALL ^ E_NOTICE);
ini_set("allow_url_fopen", 1);
ini_set("display_errors", 1);
ini_set('default_charset', 'utf-8');
define("FILE_PATH", dirname(__FILE__)."/../../");
set_include_path(get_include_path() . PATH_SEPARATOR . FILE_PATH . PATH_SEPARATOR . FILE_PATH . "/src/" . PATH_SEPARATOR . FILE_PATH . "/src/classes/");
ini_set("memory_limit", "256M");
if(defined("POCKETMINE_COMPILE") and POCKETMINE_COMPILE === true){
define("FILE_PATH", realpath(dirname(__FILE__))."/");
}else{
define("FILE_PATH", realpath(dirname(__FILE__)."/../")."/");
}
set_include_path(get_include_path() . PATH_SEPARATOR . FILE_PATH);
ini_set("memory_limit", "256M"); //Default
define("LOG", true);
define("MAGIC", "\x00\xff\xff\x00\xfe\xfe\xfe\xfe\xfd\xfd\xfd\xfd\x12\x34\x56\x78");
define("TEST_MD5", "d0ca3786e53b615bb4fb9f5094d5c9a7");
define("MAJOR_VERSION", "Alpha_1.0.7");
define("CURRENT_PROTOCOL", 5);
define("CURRENT_MINECRAFT_VERSION", "v0.5.0 alpha");
define("TEST_MD5", "ffe889db5932db1e3371d48773590e59");
define("MAJOR_VERSION", "Alpha_1.2.1");
define("CURRENT_STRUCTURE", 5);
define("CURRENT_PROTOCOL", 9);
define("CURRENT_MINECRAFT_VERSION", "v0.6.1 alpha");
define("CURRENT_API_VERSION", 4);
define("CURRENT_PHP_VERSION", "5.4.12");

158
src/constants/BlockIDs.php Normal file
View File

@ -0,0 +1,158 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
define("AIR", 0);
define("STONE", 1);
define("GRASS", 2);
define("DIRT", 3);
define("COBBLESTONE", 4);
define("COBBLE", 4);
define("PLANK", 5);
define("PLANKS", 5);
define("WOODEN_PLANK", 5);
define("SAPLING", 6);
define("SAPLINGS", 6);
define("BEDROCK", 7);
define("WATER", 8);
define("STILL_WATER", 9);
define("LAVA", 10);
define("STILL_LAVA", 11);
define("SAND", 12);
define("GRAVEL", 13);
define("GOLD_ORE", 14);
define("IRON_ORE", 15);
define("COAL_ORE", 16);
define("WOOD", 17);
define("TRUNK", 17);
define("LEAVES", 18);
define("LEAVE", 18);
define("GLASS", 20);
define("LAPIS_ORE", 21);
define("LAPIS_BLOCK", 22);
define("SANDSTONE", 24);
define("BED_BLOCK", 26);
define("COBWEB", 30);
define("TALL_GRASS", 31);
define("BUSH", 32);
define("DEAD_BUSH", 32);
define("WOOL", 35);
define("DANDELION", 37);
define("ROSE", 38);
define("CYAN_FLOWER", 38);
define("BROWN_MUSHROOM", 39);
define("RED_MUSHROOM", 40);
define("GOLD_BLOCK", 41);
define("IRON_BLOCK", 42);
define("DOUBLE_SLAB", 43);
define("DOUBLE_SLABS", 43);
define("SLAB", 44);
define("SLABS", 44);
define("BRICKS", 45);
define("BRICKS_BLOCK", 45);
define("TNT", 46);
define("BOOKSHELF", 47);
define("MOSS_STONE", 48);
define("MOSSY_STONE", 48);
define("OBSIDIAN", 49);
define("TORCH", 50);
define("FIRE", 51);
define("WOOD_STAIRS", 53);
define("WOODEN_STAIRS", 53);
define("CHEST", 54);
define("DIAMOND_ORE", 56);
define("DIAMOND_BLOCK", 57);
define("CRAFTING_TABLE", 58);
define("WORKBENCH", 58);
define("WHEAT_BLOCK", 59);
define("FARMLAND", 60);
define("FURNACE", 61);
define("BURNING_FURNACE", 62);
define("LIT_FURNACE", 62);
define("SIGN_POST", 63);
define("DOOR_BLOCK", 64);
define("WOODEN_DOOR_BLOCK", 64);
define("WOOD_DOOR_BLOCK", 64);
define("LADDER", 65);
define("COBBLE_STAIRS", 67);
define("COBBLESTONE_STAIRS", 67);
define("WALL_SIGN", 68);
define("IRON_DOOR_BLOCK", 71);
define("REDSTONE_ORE", 73);
define("GLOWING_REDSTONE_ORE", 74);
define("LIT_REDSTONE_ORE", 74);
define("SNOW", 78);
define("SNOW_LAYER", 78);
define("ICE", 79);
define("SNOW_BLOCK", 80);
define("CACTUS", 81);
define("CLAY_BLOCK", 82);
define("SUGARCANE_BLOCK", 83);
define("FENCE", 85);
define("NETHERRACK", 87);
define("SOUL_SAND", 88);
define("GLOWSTONE_BLOCK", 89);
define("TRAPDOOR", 96);
define("STONE_BRICKS", 98);
define("STONE_BRICK", 98);
define("GLASS_PANE", 102);
define("GLASS_PANEL", 102);
define("MELON_BLOCK", 103);
define("MELON_STEM", 105);
define("FENCE_GATE", 107);
define("BRICK_STAIRS", 108);
define("STONE_BRICK_STAIRS", 109);
define("NETHER_BRICKS", 112);
define("NETHER_BRICKS_STAIRS", 114);
define("SANDSTONE_STAIRS", 128);
define("QUARTZ_BLOCK", 155);
define("QUARTZ_STAIRS", 156);
define("STONECUTTER", 245);
define("GLOWING_OBSIDIAN", 246);
define("NETHER_REACTOR", 247);

View File

@ -0,0 +1,31 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
//Gamemodes
define("SURVIVAL", 0);
define("CREATIVE", 1);
define("ADVENTURE", 2);

145
src/constants/ItemIDs.php Normal file
View File

@ -0,0 +1,145 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
define("IRON_SHOVEL", 256);//Implemented
define("IRON_PICKAXE", 257);//Implemented
define("IRON_AXE", 258);//Implemented
define("FLINT_STEEL", 259);
define("APPLE", 260);//Implemented
define("BOW", 261);
define("ARROW", 262);
define("COAL", 263);//Implemented
define("DIAMOND", 264);//Implemented
define("IRON_INGOT", 265);//Implemented
define("GOLD_INGOT", 266);//Implemented
define("IRON_SWORD", 267);
define("WOODEN_SWORD", 268);
define("WOODEN_SHOVEL", 269);
define("WOODEN_PICKAXE", 270);
define("WOODEN_AXE", 271);
define("STONE_SWORD", 272);
define("STONE_SHOVEL", 273);
define("STONE_PICKAXE", 274);
define("STONE_AXE", 275);
define("DIAMOND_SWORD", 276);
define("DIAMOND_SHOVEL", 277);
define("DIAMOND_PICKAXE", 278);
define("DIAMOND_AXE", 279);
define("STICK", 280);//Implemented
define("BOWL", 281);//Implemented
define("MUSHROOM_STEW", 282);
define("GOLD_SWORD", 283);
define("GOLD_SHOVEL", 284);
define("GOLD_PICKAXE", 285);
define("GOLD_AXE", 286);
define("STRING", 287);
define("FEATHER", 288);//Implemented
define("GUNPOWDER", 289);
define("WOODEN_HOE", 290);
define("STONE_HOE", 291);
define("IRON_HOE", 292);//Implemented
define("DIAMOND_HOE", 293);
define("GOLD_HOE", 294);
define("SEEDS", 295);
define("WHEAT_SEEDS", 295);
define("WHEAT", 296);
define("BREAD", 297);
define("LEATHER_CAP", 298);
define("LEATHER_TUNIC", 299);
define("LEATHER_PANTS", 300);
define("LEATHER_BOOTS", 301);
define("CHAIN_HELMET", 302);
define("CHAIN_CHESTPLATE", 303);
define("CHAIN_LEGGINS", 304);
define("CHAIN_BOOTS", 305);
define("IRON_HELMET", 306);
define("IRON_CHESTPLATE", 307);
define("IRON_LEGGINS", 308);
define("IRON_BOOTS", 309);
define("DIAMOND_HELMET", 310);
define("DIAMOND_CHESTPLATE", 311);
define("DIAMOND_LEGGINS", 312);
define("DIAMOND_BOOTS", 313);
define("GOLD_HELMET", 314);
define("GOLD_CHESTPLATE", 315);
define("GOLD_LEGGINS", 316);
define("GOLD_BOOTS", 317);
define("FLINT", 318);
define("RAW_PORKCHOP", 319);
define("COOKED_PORKCHOP", 320);
define("PAINTING", 321);
define("GOLDEN_APPLE", 322);
define("SIGN", 323);
define("WOODEN_DOOR", 324);
define("IRON_DOOR", 330);
define("SNOWBALL", 332);
define("LEATHER", 334);
define("BRICK", 336);
define("CLAY", 337);
define("SUGARCANE", 338);
define("SUGAR_CANE", 338);
define("SUGAR_CANES", 338);
define("PAPER", 339);
define("SLIMEBALL", 341);
define("EGG", 344);
define("COMPASS", 345);
define("GLOWSTONE_DUST", 348);
define("RAW_FISH", 349);
define("COOKED_FISH", 350);
define("DYE", 351);
define("BONE", 352);
define("SUGAR", 353);
define("BED", 355);
define("COOKIE", 357);
define("SHEARS", 359);
define("MELON", 360);
define("MELON_SLICE", 360);
define("MELON_SEEDS", 362);
define("RAW_BEEF", 363);
define("STEAK", 364);
define("COOKED_BEEF", 364);
define("RAW_CHICKEN", 365);
define("COOKED_CHICKEN", 366);
define("NETHER_BRICK", 405);
define("QUARTZ", 406);
define("NETHER_QUARTZ", 406);
define("CAMERA", 456);

View File

@ -0,0 +1,346 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
define("MC_KEEP_ALIVE", 0x00);
define("MC_CLIENT_CONNECT", 0x09);
define("MC_SERVER_HANDSHAKE", 0x10);
define("MC_CLIENT_HANDSHAKE", 0x13);
define("MC_DISCONNECT", 0x15);
define("MC_LOGIN", 0x82);
define("MC_LOGIN_STATUS", 0x83);
define("MC_READY", 0x84);
define("MC_CHAT", 0x85);
define("MC_SET_TIME", 0x86);
define("MC_START_GAME", 0x87);
define("MC_ADD_MOB", 0x88);
define("MC_ADD_PLAYER", 0x89);
//define("MC_REMOVE_PLAYER", 0x8a);
define("MC_ADD_ENTITY", 0x8c);
define("MC_REMOVE_ENTITY", 0x8d);
define("MC_ADD_ITEM_ENTITY", 0x8e);
define("MC_TAKE_ITEM_ENTITY", 0x8f);
define("MC_MOVE_ENTITY", 0x90);
define("MC_MOVE_ENTITY_POSROT", 0x93);
define("MC_MOVE_PLAYER", 0x94);
define("MC_PLACE_BLOCK", 0x95);
define("MC_REMOVE_BLOCK", 0x96);
define("MC_UPDATE_BLOCK", 0x97);
define("MC_ADD_PAINTING", 0x98);
define("MC_EXPLOSION", 0x99);
define("MC_LEVEL_EVENT", 0x9a);
//define("MC_TILE_EVENT", 0x9b);
define("MC_ENTITY_EVENT", 0x9c);
define("MC_REQUEST_CHUNK", 0x9d);
define("MC_CHUNK_DATA", 0x9e);
define("MC_PLAYER_EQUIPMENT", 0x9f);
define("MC_PLAYER_ARMOR_EQUIPMENT", 0xa0);
define("MC_INTERACT", 0xa1);
define("MC_USE_ITEM", 0xa2);
define("MC_PLAYER_ACTION", 0xa3);
define("MC_HURT_ARMOR", 0xa5);
define("MC_SET_ENTITY_DATA", 0xa6);
define("MC_SET_ENTITY_MOTION", 0xa7);
define("MC_SET_HEALTH", 0xa8);
define("MC_SET_SPAWN_POSITION", 0xa9);
define("MC_ANIMATE", 0xaa);
define("MC_RESPAWN", 0xab);
define("MC_SEND_INVENTORY", 0xac);
define("MC_DROP_ITEM", 0xad);
define("MC_CONTAINER_OPEN", 0xae);
define("MC_CONTAINER_CLOSE", 0xaf);
define("MC_CONTAINER_SET_SLOT", 0xb0);
//define("MC_CONTAINER_SET_DATA", 0xb1);
//define("MC_CONTAINER_SET_CONTENT", 0xb2);
//define("MC_CONTAINER_ACK", 0xb3);
define("MC_CLIENT_MESSAGE", 0xb4);
define("MC_SIGN_UPDATE", 0xb5);
define("MC_ADVENTURE_SETTINGS", 0xb6);
class Protocol{
public static $dataName = array(
MC_KEEP_ALIVE => "Keep Alive",
MC_CLIENT_CONNECT => "Client Connect",
MC_SERVER_HANDSHAKE => "Server Handshake",
MC_CLIENT_HANDSHAKE => "Client Handshake",
MC_DISCONNECT => "Disconnect",
0x18 => "Unknown",
MC_LOGIN => "Login",
MC_LOGIN_STATUS => "Login Status",
MC_READY => "Ready",
MC_CHAT => "Chat",
MC_SET_TIME => "Set Time",
MC_START_GAME => "Start Game",
MC_ADD_MOB => "Add Mob",
MC_ADD_PLAYER => "Add Player",
MC_ADD_ENTITY => "Add Entity",
MC_REMOVE_ENTITY => "Remove Entity",
MC_ADD_ITEM_ENTITY => "Add Item",
MC_TAKE_ITEM_ENTITY => "Take Item",
MC_MOVE_ENTITY => "Move Entity",
MC_MOVE_ENTITY_POSROT => "Move Entity PosRot",
MC_MOVE_PLAYER => "Move Player",
MC_PLACE_BLOCK => "Place Block",
MC_REMOVE_BLOCK => "Remove Block",
MC_UPDATE_BLOCK => "Update Block",
MC_ADD_PAINTING => "Add Painting",
MC_EXPLOSION => "Explosion",
MC_LEVEL_EVENT => "Level Event",
MC_ENTITY_EVENT => "Entity Event",
MC_REQUEST_CHUNK => "Chunk Request",
MC_CHUNK_DATA => "Chunk Data",
MC_PLAYER_EQUIPMENT => "Player Equipment",
MC_PLAYER_ARMOR_EQUIPMENT => "Player Armor",
MC_INTERACT => "Interact",
MC_USE_ITEM => "Use Item",
MC_PLAYER_ACTION => "Player Action",
MC_SET_ENTITY_DATA => "Entity Data",
MC_SET_ENTITY_MOTION => "Entity Motion",
MC_HURT_ARMOR => "Hurt Armor",
MC_SET_HEALTH => "Set Health",
MC_SET_SPAWN_POSITION => "Set Spawn Position",
MC_ANIMATE => "Animate",
MC_RESPAWN => "Respawn",
MC_SEND_INVENTORY => "Send Inventory",
MC_DROP_ITEM => "Drop Item",
MC_CONTAINER_OPEN => "Open Container",
MC_CONTAINER_CLOSE => "Close Container",
MC_CONTAINER_SET_SLOT => "Set Container Slot",
MC_CLIENT_MESSAGE => "Client Message",
MC_SIGN_UPDATE => "Sign Update",
MC_ADVENTURE_SETTINGS => "Adventure Settings",
);
public static $packetName = array(
0x02 => "ID_UNCONNECTED_PING_OPEN_CONNECTIONS", //RakNet
0x05 => "ID_OPEN_CONNECTION_REQUEST_1", //RakNet
0x06 => "ID_OPEN_CONNECTION_REPLY_1", //RakNet
0x07 => "ID_OPEN_CONNECTION_REQUEST_2", //RakNet
0x08 => "ID_OPEN_CONNECTION_REPLY_2", //RakNet
0x1a => "ID_INCOMPATIBLE_PROTOCOL_VERSION", //RakNet
0x1c => "ID_UNCONNECTED_PONG", //RakNet
0x1d => "ID_ADVERTISE_SYSTEM", //RakNet
0x80 => "Custom Packet", //Minecraft Implementation
0x84 => "Custom Packet", //Minecraft Implementation
0x88 => "Custom Packet", //Minecraft Implementation
0x8c => "Custom Packet", //Minecraft Implementation
0xa0 => "NACK", //Minecraft Implementation
0xc0 => "ACK", //Minecraft Implementation
);
public static $raknet = array(
0x02 => array(
"long", //Ping ID
"magic",
),
0x05 => array(
"magic",
"byte", //Protocol Version
"special1", //MTU Size Null Lenght
),
0x06 => array(
"magic",
"long", //Server GUID
"byte", //Server Security
"short", //MTU Size
),
0x07 => array(
"magic",
5, //Security Cookie (idk why it's sent here)
"short", //Server UDP Port
"short", //MTU Size
"long", //Client GUID
),
0x08 => array(
"magic",
"long", //Server GUID
"short", //Client UDP Port
"short", //MTU Size
"byte", //Security
),
0x1a => array(
"byte", //Server Version
"magic",
"long", //Server GUID
),
0x1c => array(
"long", //Ping ID
"long", //Server GUID
"magic",
"string", //Data
),
0x1d => array(
"long", //Ping ID
"long", //Server GUID
"magic",
"string", //Data
),
0x80 => array(
"itriad",
"ubyte",
"customData",
),
0x81 => array(
"itriad",
"ubyte",
"customData",
),
0x82 => array(
"itriad",
"ubyte",
"customData",
),
0x83 => array(
"itriad",
"ubyte",
"customData",
),
0x84 => array(
"itriad",
"ubyte",
"customData",
),
0x85 => array(
"itriad",
"ubyte",
"customData",
),
0x86 => array(
"itriad",
"ubyte",
"customData",
),
0x87 => array(
"itriad",
"ubyte",
"customData",
),
0x88 => array(
"itriad",
"ubyte",
"customData",
),
0x89 => array(
"itriad",
"ubyte",
"customData",
),
0x8a => array(
"itriad",
"ubyte",
"customData",
),
0x8b => array(
"itriad",
"ubyte",
"customData",
),
0x8c => array(
"itriad",
"ubyte",
"customData",
),
0x8d => array(
"itriad",
"ubyte",
"customData",
),
0x8e => array(
"itriad",
"ubyte",
"customData",
),
0x8f => array(
"itriad",
"ubyte",
"customData",
),
0xa0 => array(
"short",
"bool",
"itriad",
"special1",
),
0xc0 => array(
"short",
"bool",
"itriad",
"special1",
),
);
}

View File

@ -25,8 +25,12 @@ the Free Software Foundation, either version 3 of the License, or
*/
/***REM_START***/
require_once(dirname(__FILE__)."/config.php");
require_once("common/functions.php");
require_once(FILE_PATH."/src/functions.php");
/***REM_END***/
define(DATA_PATH, realpath(arg("data-path", FILE_PATH))."/");
if(strpos(strtoupper(php_uname("s")), "WIN") === false or arg("enable-ansi", false) === true){
define("ENABLE_ANSI", true);
}else{
@ -36,57 +40,57 @@ set_error_handler("fatal_handler", E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_
$errors = 0;
if(version_compare("5.3.3", PHP_VERSION) > 0){
console("[ERROR] Use PHP >= 5.3.3", true, true, 0);
++$errors;
}elseif(version_compare("5.5.0", PHP_VERSION) <= 0){
console("[NOTICE] PocketMine-MP hasn't been tested with PHP >= 5.5", true, true, 0);
if(version_compare("5.4.0", PHP_VERSION) > 0){
console("[ERROR] Use PHP >= 5.4.0", true, true, 0);
++$errors;
}
if(version_compare("5.4.0", PHP_VERSION) > 0){
console("[NOTICE] Use PHP >= 5.4.0 to increase performance", true, true, 0);
define("HEX2BIN", false);
}else{
define("HEX2BIN", true);
if(version_compare(CURRENT_PHP_VERSION, PHP_VERSION) > 0){
console("[NOTICE] PocketMine-MP hasn't been tested with PHP < ".CURRENT_PHP_VERSION, true, true, 0);
}elseif(version_compare(CURRENT_PHP_VERSION, PHP_VERSION) < 0){
console("[NOTICE] PocketMine-MP hasn't been tested with PHP > ".CURRENT_PHP_VERSION, true, true, 0);
}
if(php_sapi_name() !== "cli"){
console("[ERROR] Use PHP-CLI to execute the library or create your own", true, true, 0);
console("[ERROR] You must run PocketMine-MP using the CLI.", true, true, 0);
++$errors;
}
if(!extension_loaded("sockets") and @dl((PHP_SHLIB_SUFFIX === "dll" ? "php_":"") . "sockets." . PHP_SHLIB_SUFFIX) === false){
console("[ERROR] Unable to find Socket extension", true, true, 0);
console("[ERROR] Unable to find the Socket extension.", true, true, 0);
++$errors;
}
if(!extension_loaded("pthreads") and @dl((PHP_SHLIB_SUFFIX === "dll" ? "php_":"") . "pthreads." . PHP_SHLIB_SUFFIX) === false){
console("[ERROR] Unable to find pthreads extension. Use the Installer available in the Homepage", true, true, 0);
console("[ERROR] Unable to find the pthreads extension.", true, true, 0);
++$errors;
}
if(!extension_loaded("curl") and @dl((PHP_SHLIB_SUFFIX === "dll" ? "php_":"") . "curl." . PHP_SHLIB_SUFFIX) === false){
console("[ERROR] Unable to find cURL extension", true, true, 0);
console("[ERROR] Unable to find the cURL extension.", true, true, 0);
++$errors;
}
if(!extension_loaded("sqlite3") and @dl((PHP_SHLIB_SUFFIX === "dll" ? "php_":"") . "sqlite3." . PHP_SHLIB_SUFFIX) === false){
console("[ERROR] Unable to find SQLite3 extension", true, true, 0);
console("[ERROR] Unable to find the SQLite3 extension.", true, true, 0);
++$errors;
}
if(!extension_loaded("zlib") and @dl((PHP_SHLIB_SUFFIX === "dll" ? "php_":"") . "zlib." . PHP_SHLIB_SUFFIX) === false){
console("[ERROR] Unable to find Zlib extension. Compressed worlds won't be loaded", true, true, 0);
define("ZLIB_EXTENSION", false);
}else{
define("ZLIB_EXTENSION", true);
console("[ERROR] Unable to find the Zlib extension.", true, true, 0);
++$errors;
}
if(!extension_loaded("gmp") and @dl((PHP_SHLIB_SUFFIX === "dll" ? "php_":"") . "gmp." . PHP_SHLIB_SUFFIX) === false){
console("[ERROR] Unable to find the GMP extension.", true, true, 0);
++$errors;
}
if($errors > 0){
die();
console("[ERROR] Please use the installer provided on the homepage.", true, true, 0);
exit(1); //Exit with error
}
require_all(FILE_PATH . "src/classes/");
?>
/***REM_START***/
require_all(FILE_PATH . "src/");
/***REM_END***/

View File

@ -46,16 +46,20 @@ function kill($pid){
function require_all($path, &$count = 0){
$dir = dir($path."/");
$dirs = array();
while(false !== ($file = $dir->read())){
if($file !== "." and $file !== ".."){
if(!is_dir($path.$file) and strtolower(substr($file, -3)) === "php"){
require_once($path.$file);
++$count;
}elseif(is_dir($path.$file)){
require_all($path.$file."/", $count);
$dirs[] = $path.$file."/";
}
}
}
foreach($dirs as $dir){
require_all($dir, $count);
}
}
@ -203,13 +207,7 @@ function console($message, $EOL = true, $log = true, $level = 1){
}
function fatal_handler($errno, $errstr, $errfile, $errline){
global $lasttrace;
console("[ERROR] A level ".$errno." error happened: \"$errstr\" in \"$errfile\" at line $errline", true, true, 0);
ob_start();
debug_print_backtrace();
$lasttrace = ob_get_contents();
ob_end_clean();
console("[ERROR] [Backtrace] $lasttrace", true, true, 0);
return false;
}
@ -221,7 +219,7 @@ function logg($message, $name, $EOL = true, $level = 2, $close = false){
$fpointers = array();
}
if(!isset($fpointers[$name]) or $fpointers[$name] === false){
$fpointers[$name] = @fopen(FILE_PATH."logs/".$name.".log", "ab");
$fpointers[$name] = @fopen(DATA_PATH."logs/".$name.".log", "ab");
}
@fwrite($fpointers[$name], $message);
if($close === true){

221
src/material/Block.php Normal file
View File

@ -0,0 +1,221 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
/***REM_START***/
require_once(FILE_PATH."/src/math/Vector3.php");
/***REM_END***/
abstract class Block extends Vector3{
public static $class = array(
AIR => "AirBlock",
STONE => "StoneBlock",
GRASS => "GrassBlock",
DIRT => "DirtBlock",
COBBLESTONE => "CobblestoneBlock",
PLANKS => "PlanksBlock",
SAPLING => "SaplingBlock",
BEDROCK => "BedrockBlock",
WATER => "WaterBlock",
STILL_WATER => "StillWaterBlock",
LAVA => "LavaBlock",
STILL_LAVA => "StillLavaBlock",
SAND => "SandBlock",
GRAVEL => "GravelBlock",
GOLD_ORE => "GoldOreBlock",
IRON_ORE => "IronOreBlock",
COAL_ORE => "CoalOreBlock",
WOOD => "WoodBlock",
LEAVES => "LeavesBlock",
GLASS => "GlassBlock",
LAPIS_ORE => "LapisOreBlock",
LAPIS_BLOCK => "LapisBlock",
SANDSTONE => "SandstoneBlock",
BED_BLOCK => "BedBlock",
COBWEB => "CobwebBlock",
TALL_GRASS => "TallGrassBlock",
DEAD_BUSH => "DeadBushBlock",
WOOL => "WoolBlock",
DANDELION => "DandelionBlock",
CYAN_FLOWER => "CyanFlowerBlock",
BROWN_MUSHROOM => "BrownMushroomBlock",
RED_MUSHROOM => "RedMushRoomBlock",
GOLD_BLOCK => "GoldBlock",
IRON_BLOCK => "IronBlock",
DOUBLE_SLAB => "DoubleSlabBlock",
SLAB => "SlabBlock",
BRICKS_BLOCK => "BricksBlock",
TNT => "TNTBlock",
BOOKSHELF => "BookshelfBlock",
MOSS_STONE => "MossStoneBlock",
OBSIDIAN => "ObsidianBlock",
TORCH => "TorchBlock",
FIRE => "FireBlock",
WOOD_STAIRS => "WoodStairsBlock",
CHEST => "ChestBlock",
DIAMOND_ORE => "DiamondOreBlock",
DIAMOND_BLOCK => "DiamondBlock",
WORKBENCH => "WorkbenchBlock",
WHEAT_BLOCK => "WheatBlock",
FARMLAND => "FarmlandBlock",
FURNACE => "FurnaceBlock",
BURNING_FURNACE => "BurningFurnaceBlock",
SIGN_POST => "SignPostBlock",
WOOD_DOOR_BLOCK => "WoodDoorBlock",
LADDER => "LadderBlock",
COBBLESTONE_STAIRS => "CobblestoneStairsBlock",
WALL_SIGN => "WallSignBlock",
IRON_DOOR_BLOCK => "IronDoorBlock",
REDSTONE_ORE => "RedstoneOreBlock",
GLOWING_REDSTONE_ORE => "GlowingRedstoneOreBlock",
SNOW_LAYER => "SnowLayerBlock",
ICE => "IceBlock",
SNOW_BLOCK => "SnowBlock",
CACTUS => "CactusBlock",
CLAY_BLOCK => "ClayBlock",
SUGARCANE_BLOCK => "SugarcaneBlock",
FENCE => "FenceBlock",
NETHERRACK => "NetherrackBlock",
SOUL_SAND => "SoulSandBlock",
GLOWSTONE_BLOCK => "GlowstoneBlock",
TRAPDOOR => "TrapdoorBlock",
STONE_BRICKS => "StoneBricksBlock",
GLASS_PANE => "GlassPaneBlock",
MELON_BLOCK => "MelonBlock",
MELON_STEM => "MelonStemBlock",
FENCE_GATE => "FenceGateBlock",
BRICK_STAIRS => "BrickStairsBlock",
STONE_BRICK_STAIRS => "StoneBrickStairsBlock",
NETHER_BRICKS => "NetherBricksBlock",
NETHER_BRICKS_STAIRS => "NetherBricksStairsBlock",
SANDSTONE_STAIRS => "SandstoneStairsBlock",
QUARTZ_BLOCK => "QuartzBlock",
QUARTZ_STAIRS => "QuartzStairsBlock",
STONECUTTER => "StonecutterBlock",
GLOWING_OBSIDIAN => "GlowingObsidianBlock",
NETHER_REACTOR => "NetherReactorBlock",
);
protected $id;
protected $meta;
protected $name;
protected $breakTime;
public $isActivable = false;
public $breakable = true;
public $isFlowable = false;
public $isTransparent = false;
public $isReplaceable = false;
public $isPlaceable = true;
public $inWorld = false;
public $hasPhysics = false;
public $isLiquid = false;
public $x;
public $y;
public $z;
public function __construct($id, $meta = 0, $name = "Unknown"){
$this->id = (int) $id;
$this->meta = (int) $meta;
$this->name = $name;
$this->breakTime = 0.25;
}
public function getName(){
return $this->name;
}
final public function getID(){
return $this->id;
}
final public function getMetadata(){
return $this->meta & 0x0F;
}
final public function position(Vector3 $v){
$this->inWorld = true;
$this->x = (int) $v->x;
$this->y = (int) $v->y;
$this->z = (int) $v->z;
}
public function getDrops(Item $item, Player $player){
if(!isset(Block::$class[$this->id])){ //Unknown blocks
return array();
}else{
return array(
array($this->id, $this->meta, 1),
);
}
}
public function getBreakTime(Item $item, Player $player){
if($player->gamemode === CREATIVE){
return 0.25;
}
return $this->breakTime;
}
final public function __toString(){
return "Block ". $this->name ." (".$this->id.":".$this->meta.")";
}
abstract function isBreakable(Item $item, Player $player);
abstract function onBreak(BlockAPI $level, Item $item, Player $player);
abstract function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz);
abstract function onActivate(BlockAPI $level, Item $item, Player $player);
abstract function onUpdate(BlockAPI $level, $type);
}
/***REM_START***/
require_once("block/GenericBlock.php");
require_once("block/SolidBlock.php");
require_once("block/TransparentBlock.php");
require_once("block/FallableBlock.php");
require_once("block/LiquidBlock.php");
require_once("block/StairBlock.php");
require_once("block/DoorBlock.php");
/***REM_END***/

142
src/material/Item.php Normal file
View File

@ -0,0 +1,142 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class Item{
public static $class = array(
SUGARCANE => "SugarcaneItem",
WHEAT_SEEDS => "WheatSeedsItem",
MELON_SEEDS => "MelonSeedsItem",
SIGN => "SignItem",
WOODEN_DOOR => "WoodenDoorItem",
IRON_DOOR => "IronDoorItem",
BED => "BedItem",
PAINTING => "PaintingItem",
COAL => "CoalItem",
APPLE => "AppleItem",
DIAMOND => "DiamondItem",
STICK => "StickItem",
BOWL => "BowlItem",
FEATHER => "FeatherItem",
BRICK => "BrickItem",
IRON_INGOT => "IronIngotItem",
GOLD_INGOT => "GoldIngotItem",
IRON_SHOVEL => "IronShovelItem",
IRON_PICKAXE => "IronPickaxeItem",
IRON_AXE => "IronAxeItem",
IRON_HOE => "IronHoeItem",
);
protected $block;
protected $id;
protected $meta;
public $count;
protected $maxStackSize = 64;
protected $durability = 0;
protected $name;
public $isActivable = false;
public function __construct($id, $meta = 0, $count = 1, $name = "Unknown"){
$this->id = (int) $id;
$this->meta = (int) $meta;
$this->count = (int) $count;
$this->name = $name;
if(!isset($this->block) and $this->id <= 0xff and isset(Block::$class[$this->id])){
$this->block = BlockAPI::get($this->id, $this->meta);
$this->name = $this->block->getName();
}
}
public function getName(){
return $this->name;
}
public function isPlaceable(){
return (($this->block instanceof Block) and $this->block->isPlaceable === true);
}
public function getBlock(){
if($this->block instanceof Block){
return $this->block;
}else{
return BlockAPI::get(AIR);
}
}
public function getID(){
return $this->id;
}
public function getMetadata(){
return $this->meta;
}
public function getMaxStackSize(){
return $this->maxStackSize;
}
public function isPickaxe(){ //Returns false or level of the pickaxe
switch($this->id){
case IRON_PICKAXE:
return 3;
case WOODEN_PICKAXE:
return 1;
case STONE_PICKAXE:
return 2;
case DIAMOND_PICKAXE:
return 4;
case GOLD_PICKAXE:
return 3;
default:
return false;
}
}
public function isHoe(){
switch($this->id){
case IRON_HOE:
case WOODEN_HOE:
case STONE_HOE:
case DIAMOND_HOE:
case GOLD_HOE:
return true;
default:
return false;
}
}
final public function __toString(){
return "Item ". $this->name ." (".$this->id.":".$this->meta.")";
}
public function getDestroySpeed(Block $block, Player $player){
return 1;
}
public function onActivate(BlockAPI $level, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
return false;
}
}

View File

@ -0,0 +1,96 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class DoorBlock extends TransparentBlock{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true and $face === 1){
$blockUp = $level->getBlockFace($block, 1);
$blockDown = $level->getBlockFace($block, 0);
if($blockUp->isReplaceable === false or $blockDown->isTransparent === true){
return false;
}
$direction = $player->entity->getDirection();
$face = array(
0 => 3,
1 => 4,
2 => 2,
3 => 5,
);
$next = $level->getBlockFace($block, $face[(($direction + 2) % 4)]);
$next2 = $level->getBlockFace($block, $face[$direction]);
$metaUp = 0x08;
if($next->getID() === $this->id or ($next2->isTransparent === false and $next->isTransparent === true)){ //Door hinge
$metaUp |= 0x01;
}
$level->setBlock($blockUp, $this->id, $metaUp); //Top
$this->meta = $direction & 0x03;
$level->setBlock($block, $this->id, $this->meta); //Bottom
return true;
}
return false;
}
public function onBreak(BlockAPI $level, Item $item, Player $player){
if($this->inWorld === true){
if(($this->meta & 0x08) === 0x08){
$down = $level->getBlockFace($this, 0);
if($down->getID() === $this->id){
$level->setBlock($down, 0, 0);
}
}else{
$up = $level->getBlockFace($this, 1);
if($up->getID() === $this->id){
$level->setBlock($up, 0, 0);
}
}
$level->setBlock($this, 0, 0);
return true;
}
return false;
}
public function onActivate(BlockAPI $level, Item $item, Player $player){
if(($this->meta & 0x08) === 0x08){ //Top
$down = $level->getBlockFace($this, 0);
if($down->getID() === $this->id){
$meta = $down->getMetadata() ^ 0x04;
$level->setBlock($down, $this->id, $meta);
return true;
}
return false;
}else{
$this->meta ^= 0x04;
$level->setBlock($this, $this->id, $this->meta);
}
return true;
}
}

View File

@ -25,14 +25,9 @@ the Free Software Foundation, either version 3 of the License, or
*/
class Sapling{
const OAK = 0;
const SPRUCE = 1;
const BIRCH = 2;
const BURN_TIME = 5;
public static function growTree(LevelAPI $level, $block, $type){
$type = $type & 0x03;
TreeObject::growTree($level, $block, $type);
class FallableBlock extends GenericBlock{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
$this->hasPhysics = true;
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class FlowableBlock extends TransparentBlock{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
$this->isFlowable = true;
}
}

View File

@ -0,0 +1,59 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class GenericBlock extends Block{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$level->setBlock($block, $this->id, $this->getMetadata());
return true;
}
return false;
}
public function isBreakable(Item $item, Player $player){
return $this->breakable;
}
public function onBreak(BlockAPI $level, Item $item, Player $player){
if($this->inWorld === true){
$level->setBlock($this, AIR, 0);
return true;
}
return false;
}
public function onUpdate(BlockAPI $level, $type){
return false;
}
public function onActivate(BlockAPI $level, Item $item, Player $player){
return false;
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class LiquidBlock extends TransparentBlock{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
$this->isLiquid = true;
$this->breakable = false;
$this->isReplaceable = true;
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class SolidBlock extends GenericBlock{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
}
}

View File

@ -0,0 +1,56 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class StairBlock extends TransparentBlock{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$faces = array(
0 => 0,
1 => 2,
2 => 1,
3 => 3,
);
$this->meta = $faces[$player->entity->getDirection()] & 0x03;
if(($fy > 0.5 and $face !== 1) or $face === 0){
$this->meta |= 0x04; //Upside-down stairs
}
$level->setBlock($block, $this->id, $this->meta);
return true;
}
return false;
}
public function getDrops(Item $item, Player $player){
return array(
array($this->id, 0, 1),
);
}
}

View File

@ -0,0 +1,38 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class TransparentBlock extends GenericBlock{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
$this->isActivable = false;
$this->breakable = true;
$this->isFlowable = false;
$this->isTransparent = true;
$this->isReplaceable = false;
$this->isPlaceable = true;
}
}

View File

@ -0,0 +1,52 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class LadderBlock extends TransparentBlock{
public function __construct($meta = 0){
parent::__construct(LADDER, $meta, "Ladder");
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
if($target->isTransparent === false){
$faces = array(
2 => 2,
3 => 3,
4 => 4,
5 => 5,
);
$level->setBlock($block, $this->id, $faces[$face]);
return true;
}
}
return false;
}
public function getDrops(Item $item, Player $player){
return array(
array($this->id, 0, 1),
);
}
}

View File

@ -0,0 +1,67 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class SignPostBlock extends TransparentBlock{
public function __construct($meta = 0){
parent::__construct(SIGN_POST, $meta, "Sign Post");
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true and $face !== 0){
if($face !== 0){
$faces = array(
2 => 2,
3 => 3,
4 => 4,
5 => 5,
);
if(!isset($faces[$face])){
$level->setBlock($block, SIGN_POST, 0);
return true;
}else{
$level->setBlock($block, WALL_SIGN, $faces[$face]);
return true;
}
}
}
return false;
}
public function onBreak(BlockAPI $level, Item $item, Player $player){
if($this->inWorld === true){
$level->setBlock($this, 0, 0, true, true);
return true;
}
return false;
}
public function getDrops(Item $item, Player $player){
return array(
array(SIGN, 0, 1),
);
}
}

View File

@ -0,0 +1,54 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class TorchBlock extends FlowableBlock{
public function __construct($meta = 0){
parent::__construct(TORCH, $meta, "Torch");
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true and $face !== 0){
if($target->isTransparent === false){
$faces = array(
1 => 5,
2 => 4,
3 => 3,
4 => 2,
5 => 1,
);
$level->setBlock($block, $this->id, $faces[$face]);
return true;
}
}
return false;
}
public function getDrops(Item $item, Player $player){
return array(
array($this->id, 0, 1),
);
}
}

View File

@ -0,0 +1,62 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class TrapdoorBlock extends TransparentBlock{
public function __construct($meta = 0){
parent::__construct(TRAPDOOR, $meta, "Trapdoor");
$this->isActivable = true;
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
if($target->isTransparent === false and $face !== 0 and $face !== 1){
$faces = array(
2 => 0,
3 => 1,
4 => 2,
5 => 3,
);
$this->meta = $faces[$face] & 0x03;
if($fy > 0.5){
$this->meta |= 0x08;
}
$level->setBlock($block, $this->id, $this->meta);
return true;
}
}
return false;
}
public function getDrops(Item $item, Player $player){
return array(
array($this->id, 0, 1),
);
}
public function onActivate(BlockAPI $level, Item $item, Player $player){
$this->meta ^= 0x04;
$level->setBlock($this, $this->id, $this->meta);
return true;
}
}

View File

@ -0,0 +1,68 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class WallSignBlock extends TransparentBlock{
public function __construct($meta = 0){
parent::__construct(WALL_SIGN, $meta, "Wall Sign");
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true and $face !== 0){
if($face !== 0){
$faces = array(
2 => 2,
3 => 3,
4 => 4,
5 => 5,
);
if(!isset($faces[$face])){
$level->setBlock($block, SIGN_POST, 0);
return true;
}else{
$level->setBlock($block, WALL_SIGN, $faces[$face]);
return true;
}
}
}
return false;
}
public function onBreak(BlockAPI $level, Item $item, Player $player){
if($this->inWorld === true){
$level->setBlock($this, AIR, 0, true, true);
return true;
}
return false;
}
public function getDrops(Item $item, Player $player){
return array(
array(SIGN, 0, 1),
);
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class LavaBlock extends LiquidBlock{
public function __construct($meta = 0){
parent::__construct(LAVA, $meta, "Lava");
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class StillLavaBlock extends LiquidBlock{
public function __construct($meta = 0){
parent::__construct(STILL_LAVA, $meta, "Still Lava");
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class StillWaterBlock extends LiquidBlock{
public function __construct($meta = 0){
parent::__construct(STILL_WATER, $meta, "Still Water");
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class WaterBlock extends LiquidBlock{
public function __construct($meta = 0){
parent::__construct(WATER, $meta, "Water");
}
}

View File

@ -0,0 +1,41 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class AirBlock extends TransparentBlock{
public function __construct(){
parent::__construct(AIR, 0, "Air");
$this->isActivable = false;
$this->breakable = false;
$this->isFlowable = true;
$this->isTransparent = true;
$this->isReplaceable = true;
$this->isPlaceable = false;
$this->inWorld = false;
$this->hasPhysics = false;
}
}

View File

@ -0,0 +1,102 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class BedBlock extends TransparentBlock{
public function __construct($type = 0){
parent::__construct(BED_BLOCK, $type, "Bed Block");
$this->isActivable = true;
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$down = $level->getBlockFace($block, 0);
if($down->isTransparent === false){
$faces = array(
0 => 3,
1 => 4,
2 => 2,
3 => 5,
);
$d = $player->entity->getDirection();
$next = $level->getBlockFace($block, $faces[(($d + 3) % 4)]);
$downNext = $level->getBlockFace($next, 0);
if($next->isReplaceable === true and $downNext->isTransparent === false){
$meta = (($d + 3) % 4) & 0x03;
$level->setBlock($block, $this->id, $meta);
$level->setBlock($next, $this->id, $meta | 0x08);
return true;
}
}
}
return false;
}
public function onBreak(BlockAPI $level, Item $item, Player $player){
if($this->inWorld === true){//Checks if the block was in the world or not. Just in case
$blockNorth = $level->getBlockFace($this, 2); //Gets the blocks around them
$blockSouth = $level->getBlockFace($this, 3);
$blockEast = $level->getBlockFace($this, 5);
$blockWest = $level->getBlockFace($this, 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
$level->setBlock($blockNorth, 0, 0);
}elseif($blockSouth->getID() === $this->id and $blockSouth->meta !== 0x08){
$level->setBlock($blockSouth, 0, 0);
}elseif($blockEast->getID() === $this->id and $blockEast->meta !== 0x08){
$level->setBlock($blockEast, 0, 0);
}elseif($blockWest->getID() === $this->id and $blockWest->meta !== 0x08){
$level->setBlock($blockWest, 0, 0);
}else{
return false;
}
return true;
}else{ //Bottom Part of Bed
if($blockNorth->getID() === $this->id and ($blockNorth->meta & 0x08) === 0x08){
$level->setBlock($blockNorth, 0, 0);
}elseif($blockSouth->getID() === $this->id and ($blockSouth->meta & 0x08) === 0x08){
$level->setBlock($blockSouth, 0, 0);
}elseif($blockEast->getID() === $this->id and ($blockEast->meta & 0x08) === 0x08){
$level->setBlock($blockEast, 0, 0);
}elseif($blockWest->getID() === $this->id and ($blockWest->meta & 0x08) === 0x08){
$level->setBlock($blockWest, 0, 0);
}else{
return false;
}
return true;
}
return false;
}
}
public function getDrops(Item $item, Player $player){
return array(
array(BED, 0, 1),
);
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class FireBlock extends FlowableBlock{
public function __construct($meta = 0){
parent::__construct(FIRE, $meta, "Fire");
$this->isReplaceable = true;
$this->breakable = false;
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class NetherReactorBlock extends SolidBlock{
public function __construct($meta = 0){
parent::__construct(NETHER_REACTOR, $meta, "Nether Reactor");
$this->isActivable = true;
}
}

View File

@ -0,0 +1,46 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class TNTBlock extends SolidBlock{
public function __construct(){
parent::__construct(TNT, 0, "TNT");
}
public function getDrops(Item $item, Player $player){
if($this->inWorld === true){
$player->dataPacket(MC_EXPLOSION, array(
"x" => $this->x,
"y" => $this->y,
"z" => $this->z,
"radius" => 2,
"records" => array(),
));
}
return array(
array(TNT, 0, 1),
);
}
}

View File

@ -25,25 +25,19 @@ the Free Software Foundation, either version 3 of the License, or
*/
class Item{
public $id;
protected $maxStackSize = 64;
private $durability = 0;
private $name = "Unknown";
public function __construct($id){
$this->id = (int) $id;
class CoalOreBlock extends SolidBlock{
public function __construct(){
parent::__construct(COAL_ORE, 0, "Coal Ore");
}
public function setMaxStackSize($size = 64){
$this->maxStackSize = (int) $size;
}
public function getDestroySpeed(Item $item, Entity $entity){
return 1;
}
public function getMaxStackSize(){
return $this->maxStackSize;
public function getDrops(Item $item, Player $player){
if($item->isPickaxe() >= 1){
return array(
array(263, 0, 1), //Coal
);
}else{
return array();
}
}
}

View File

@ -0,0 +1,42 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class DiamondOreBlock extends SolidBlock{
public function __construct(){
parent::__construct(DIAMOND_ORE, 0, "Diamond Ore");
}
public function getDrops(Item $item, Player $player){
if($item->isPickaxe() >= 3){
return array(
array(264, 0, 1),
);
}else{
return array();
}
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class GlowingRedstoneOreBlock extends SolidBlock{
public function __construct(){
parent::__construct(GLOWING_REDSTONE_ORE, 0, "Glowing Redstone Ore");
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class GoldOreBlock extends SolidBlock{
public function __construct(){
parent::__construct(GOLD_ORE, 0, "Gold Ore");
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class IronOreBlock extends SolidBlock{
public function __construct(){
parent::__construct(IRON_ORE, 0, "Iron Ore");
}
}

View File

@ -0,0 +1,43 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class LapisOreBlock extends SolidBlock{
public function __construct(){
parent::__construct(LAPIS_ORE, 0, "Lapis Ore");
}
public function getDrops(Item $item, Player $player){
if($item->isPickaxe() >= 2){
return array(
array(351, 4, mt_rand(4, 8)),
);
}else{
return array();
}
}
}

View File

@ -0,0 +1,41 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class RedstoneOreBlock extends SolidBlock{
public function __construct(){
parent::__construct(REDSTONE_ORE, 0, "Redstone Ore");
}
public function getDrops(Item $item, Player $player){
if($item->isPickaxe() >= 2){
return array(
//array(331, 4, mt_rand(4, 5)),
);
}else{
return array();
}
}
}

View File

@ -0,0 +1,44 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class BrownMushroomBlock extends FlowableBlock{
public function __construct(){
parent::__construct(BROWN_MUSHROOM, 0, "Brown Mushroom");
$this->isFlowable = true;
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$down = $level->getBlockFace($block, 0);
if($down->isTransparent === false){
$level->setBlock($block, $this->id, $this->getMetadata());
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,50 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class CactusBlock extends TransparentBlock{
public function __construct(){
parent::__construct(CACTUS, 0, "Cactus");
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$down = $level->getBlockFace($block, 0);
if($down->getID() === SAND or $down->getID() === CACTUS){
$block0 = $level->getBlockFace($block, 2);
$block1 = $level->getBlockFace($block, 3);
$block2 = $level->getBlockFace($block, 4);
$block3 = $level->getBlockFace($block, 5);
if($block0->isFlowable === true and $block1->isFlowable === true and $block2->isFlowable === true and $block3->isFlowable === true){
$level->setBlock($block, $this->id, 0);
return true;
}
}
}
return false;
}
}

View File

@ -0,0 +1,43 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class CyanFlowerBlock extends FlowableBlock{
public function __construct(){
parent::__construct(CYAN_FLOWER, 0, "Cyan Flower");
$this->isFlowable = true;
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$down = $level->getBlockFace($block, 0);
if($down->getID() === 2 or $down->getID() === 3 or $down->getID() === 60){
$level->setBlock($block, $this->id, $this->getMetadata());
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,43 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class DandelionBlock extends FlowableBlock{
public function __construct(){
parent::__construct(DANDELION, 0, "Dandelion");
$this->isFlowable = true;
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$down = $level->getBlockFace($block, 0);
if($down->getID() === 2 or $down->getID() === 3 or $down->getID() === 60){
$level->setBlock($block, $this->id, $this->getMetadata());
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class DeadBushBlock extends FlowableBlock{
public function __construct(){
parent::__construct(DEAD_BUSH, 0, "Dead Bush");
$this->isFlowable = true;
$this->isReplaceable = true;
}
}

View File

@ -0,0 +1,57 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class MelonStemBlock extends TransparentBlock{
public function __construct($meta = 0){
parent::__construct(MELON_STEM, $meta, "Melon Stem");
$this->isActivable = true;
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$down = $level->getBlockFace($block, 0);
if($down->getID() === FARMLAND){
$level->setBlock($block, $this->id, $this->getMetadata());
return true;
}
}
return false;
}
public function onActivate(BlockAPI $level, Item $item, Player $player){
if($item->getID() === DYE and $item->getMetadata() === 0x0F){ //Bonemeal
$level->setBlock($this, $this->id, 0x07);
return true;
}
return false;
}
public function getDrops(Item $item, Player $player){
return array(
array(MELON_SEEDS, 0, mt_rand(0, 2)),
);
}
}

View File

@ -0,0 +1,44 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class RedMushroomBlock extends FlowableBlock{
public function __construct(){
parent::__construct(RED_MUSHROOM, 0, "Red Mushroom");
$this->isFlowable = true;
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$down = $level->getBlockFace($block, 0);
if($down->isTransparent === false){
$level->setBlock($block, $this->id, $this->getMetadata());
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,86 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class SaplingBlock extends TransparentBlock{
const OAK = 0;
const SPRUCE = 1;
const BIRCH = 2;
const BURN_TIME = 5;
public function __construct($meta = Sapling::OAK){
parent::__construct(SAPLING, $meta, "Sapling");
$this->isActivable = true;
$this->isFlowable = true;
$names = array(
0 => "Oak Sapling",
1 => "Spruce Sapling",
2 => "Birch Sapling",
);
$this->name = $names[$this->meta & 0x03];
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$down = $level->getBlockFace($block, 0);
if($down->getID() === GRASS or $down->getID() === DIRT or $down->getID() === FARMLAND){
$level->setBlock($block, $this->id, $this->getMetadata());
return true;
}
}
return false;
}
public function onActivate(BlockAPI $level, Item $item, Player $player){
if($item->getID() === DYE and $item->getMetadata() === 0x0F){ //Bonemeal
TreeObject::growTree($level, $this);
return true;
}
return false;
}
public function onUpdate(BlockAPI $level, $type){
if($this->inWorld !== true){
return false;
}
if($type === BLOCK_UPDATE_RANDOM and mt_rand(0,2) === 0){ //Growth
if(($this->meta & 0x08) === 0x08){
TreeObject::growTree($level, $this);
}else{
$this->meta |= 0x08;
$this->level->setBlock($this->x, $this->y, $this->z, $this->id, $this->meta);
}
return true;
}
return false;
}
public function getDrops(Item $item, Player $player){
return array(
array($this->id, $this->meta & 0x03, 1),
);
}
}

View File

@ -0,0 +1,70 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class SugarcaneBlock extends TransparentBlock{
public function __construct(){
parent::__construct(SUGARCANE_BLOCK, 0, "Sugarcane");
}
public function getDrops(Item $item, Player $player){
return array(
array(SUGARCANE, 0, 1),
);
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$down = $level->getBlockFace($block, 0);
if($down->getID() === SUGARCANE_BLOCK){
$level->setBlock($block, $this->id, 0);
return true;
}elseif($down->getID() === GRASS or $down->getID() === DIRT or $down->getID() === SAND){
$block0 = $level->getBlockFace($down, 2);
$block1 = $level->getBlockFace($down, 3);
$block2 = $level->getBlockFace($down, 4);
$block3 = $level->getBlockFace($down, 5);
/*$block4 = $level->getBlockFace($block, 2);
$block5 = $level->getBlockFace($block, 3);
$block6 = $level->getBlockFace($block, 4);
$block7 = $level->getBlockFace($block, 5);*/
if($block0->getID() === WATER or $block0->getID() === STILL_WATER
or $block1->getID() === WATER or $block1->getID() === STILL_WATER
or $block2->getID() === WATER or $block2->getID() === STILL_WATER
or $block3->getID() === WATER or $block3->getID() === STILL_WATER
/*or $block4->getID() === WATER or $block4->getID() === STILL_WATER
or $block5->getID() === WATER or $block5->getID() === STILL_WATER
or $block6->getID() === WATER or $block6->getID() === STILL_WATER
or $block7->getID() === WATER or $block7->getID() === STILL_WATER*/){
$level->setBlock($block, $this->id, 0);
return true;
}
}
}
return false;
}
}

View File

@ -0,0 +1,49 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class TallGrassBlock extends FlowableBlock{
public function __construct($meta = 1){
parent::__construct(TALL_GRASS, $meta, "Tall Grass");
$this->isFlowable = true;
$this->isReplaceable = true;
$names = array(
0 => "Dead Shrub",
1 => "Tall Grass",
2 => "Fern",
);
$this->name = $names[$this->meta & 0x03];
}
public function getDrops(Item $item, Player $player){
$drops = array();
if(mt_rand(1,10) === 1){//Seeds
$drops[] = array(295, 0, 1);
}
return $drops;
}
}

View File

@ -0,0 +1,63 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class WheatBlock extends FlowableBlock{
public function __construct($meta = 0){
parent::__construct(WHEAT_BLOCK, $meta, "Wheat Block");
$this->isActivable = true;
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$down = $level->getBlockFace($block, 0);
if($down->getID() === FARMLAND){
$level->setBlock($block, $this->id, $this->getMetadata());
return true;
}
}
return false;
}
public function onActivate(BlockAPI $level, Item $item, Player $player){
if($item->getID() === DYE and $item->getMetadata() === 0x0F){ //Bonemeal
$level->setBlock($this, $this->id, 0x07);
return true;
}
return false;
}
public function getDrops(Item $item, Player $player){
$drops = array();
if($this->meta >= 0x07){
$drops[] = array(WHEAT, 0, 1);
$drops[] = array(WHEAT_SEEDS, 0, mt_rand(0, 3));
}else{
$drops[] = array(WHEAT_SEEDS, 0, 1);
}
return $drops;
}
}

View File

@ -0,0 +1,41 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class BedrockBlock extends SolidBlock{
public function __construct(){
parent::__construct(BEDROCK, 0, "Bedrock");
$this->breakable = false;
}
public function isBreakable(Item $item, Player $player){
if($player->gamemode === CREATIVE){
return true;
}
return false;
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class BookshelfBlock extends SolidBlock{
public function __construct(){
parent::__construct(BOOKSHELF, 0, "Bookshelf");
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class BricksBlock extends SolidBlock{
public function __construct(){
parent::__construct(BRICKS_BLOCK, 0, "Bricks");
}
}

View File

@ -0,0 +1,57 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class BurningFurnaceBlock extends SolidBlock{
public function __construct($meta = 0){
parent::__construct(BURNING_FURNACE, $meta, "Burning Furnace");
$this->isActivable = true;
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$faces = array(
0 => 4,
1 => 2,
2 => 5,
3 => 3,
);
$level->setBlock($block, $this->id, $faces[$player->entity->getDirection()]);
return true;
}
return false;
}
public function getDrops(Item $item, Player $player){
if($item->isPickaxe() >= 1){
return array(
array(FURNACE, 0, 1),
);
}else{
return array();
}
}
}

View File

@ -0,0 +1,128 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class ChestBlock extends SolidBlock{
public function __construct($meta = 0){
parent::__construct(CHEST, $meta, "Chest");
$this->isActivable = true;
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$faces = array(
0 => 4,
1 => 2,
2 => 5,
3 => 3,
);
$level->setBlock($block, $this->id, $faces[$player->entity->getDirection()]);
$server = ServerAPI::request();
$server->api->tileentity->add(TILE_CHEST, $this->x, $this->y, $this->z, array(
"Items" => array(),
"id" => TILE_CHEST,
"x" => $this->x,
"y" => $this->y,
"z" => $this->z
));
return true;
}
return false;
}
public function onBreak(BlockAPI $level, Item $item, Player $player){
if($this->inWorld === true){
$server = ServerAPI::request();
$t = $server->api->tileentity->get($this);
if($t !== false){
if(is_array($t)){
foreach($t as $ts){
if($ts->class === TILE_CHEST){
$server->api->tileentity->remove($ts->id);
}
}
}elseif($t->class === TILE_CHEST){
$server->api->tileentity->remove($t->id);
}
}
$level->setBlock($this, 0, 0);
return true;
}
return false;
}
public function onActivate(BlockAPI $level, Item $item, Player $player){
$server = ServerAPI::request();
$t = $server->api->tileentity->get($this);
$chest = false;
if($t !== false){
if(is_array($t)){
$chest = array_shift($t);
}else{
$chest = $t;
}
}else{
$chest = $server->api->tileentity->add(TILE_CHEST, $this->x, $this->y, $this->z, array(
"Items" => array(),
"id" => TILE_CHEST,
"x" => $this->x,
"y" => $this->y,
"z" => $this->z
));
}
if($chest->class !== TILE_CHEST){
return false;
}
$id = $player->windowCnt = $player->windowCnt++ % 255;
$player->windows[$id] = $chest;
$player->dataPacket(MC_CONTAINER_OPEN, array(
"windowid" => $id,
"type" => WINDOW_CHEST,
"slots" => 27,
"title" => "Chest",
));
foreach($chest->data["Items"] as $slot){
if($slot["Slot"] < 0 or $slot["Slot"] >= 27){
continue;
}
$player->dataPacket(MC_CONTAINER_SET_SLOT, array(
"windowid" => $id,
"slot" => $slot["Slot"],
"block" => $slot["id"],
"stack" => $slot["Count"],
"meta" => $slot["Damage"],
));
}
return true;
}
public function getDrops(Item $item, Player $player){
return array(
array($this->id, 0, 1),
);
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class ClayBlock extends SolidBlock{
public function __construct(){
parent::__construct(CLAY_BLOCK, 0, "Clay Block");
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class CobblestoneBlock extends SolidBlock{
public function __construct(){
parent::__construct(COBBLESTONE, 0, "Cobblestone");
}
}

View File

@ -0,0 +1,36 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class CobwebBlock extends FlowableBlock{
public function __construct(){
parent::__construct(COBWEB, 0, "Cobweb");
$this->isFlowable = true;
}
public function getDrops(Item $item, Player $player){
return array();
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class DiamondBlock extends SolidBlock{
public function __construct(){
parent::__construct(DIAMOND_BLOCK, 0, "Diamond Block");
}
}

View File

@ -0,0 +1,41 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class DirtBlock extends SolidBlock{
public function __construct(){
parent::__construct(DIRT, 0, "Dirt");
$this->isActivable = true;
}
public function onActivate(BlockAPI $level, Item $item, Player $player){
if($item->isHoe()){
$level->setBlock($this, FARMLAND, 0);
return true;
}
return false;
}
}

View File

@ -0,0 +1,49 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class DoubleSlabBlock extends SolidBlock{
public function __construct($meta = 0){
parent::__construct(DOUBLE_SLAB, $meta, "Double Slab");
$names = array(
0 => "Stone",
1 => "Sandstone",
2 => "Wooden",
3 => "Cobblestone",
4 => "Brick",
5 => "Stone Brick",
6 => "Nether Brick",
7 => "Quartz",
);
$this->name = "Double " . $names[$this->meta & 0x07] . " Slab";
}
public function getDrops(Item $item, Player $player){
return array(
array(SLAB, $this->meta & 0x07, 2),
);
}
}

View File

@ -0,0 +1,37 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class FarmlandBlock extends SolidBlock{
public function __construct($meta = 0){
parent::__construct(FARMLAND, $meta, "Farmland");
}
public function getDrops(Item $item, Player $player){
return array(
array(DIRT, 0, 1),
);
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class FenceBlock extends TransparentBlock{
public function __construct(){
parent::__construct(FENCE, 0, "Fence");
}
}

View File

@ -0,0 +1,63 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class FenceGateBlock extends TransparentBlock{
public function __construct($meta = 0){
parent::__construct(FENCE_GATE, $meta, "Fence Gate");
$this->isActivable = true;
}
public function place(BlockAPI $level, Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){
if($block->inWorld === true){
$faces = array(
0 => 3,
1 => 0,
2 => 1,
3 => 2,
);
$this->meta = $faces[$player->entity->getDirection()] & 0x03;
$level->setBlock($block, $this->id, $this->meta);
return true;
}
return false;
}
public function getDrops(Item $item, Player $player){
return array(
array($this->id, 0, 1),
);
}
public function onActivate(BlockAPI $level, Item $item, Player $player){
$faces = array(
0 => 3,
1 => 0,
2 => 1,
3 => 2,
);
$this->meta = ($faces[$player->entity->getDirection()] & 0x03) | ((~$this->meta) & 0x04);
$level->setBlock($this, $this->id, $this->meta);
return true;
}
}

View File

@ -0,0 +1,41 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
/***REM_START***/
require_once("BurningFurnace.php");
/***REM_END***/
class FurnaceBlock extends BurningFurnaceBlock{
public function __construct($meta = 0){
parent::__construct($meta);
$this->id = FURNACE;
$this->name = "Furnace";
$this->isActivable = true;
}
}

View File

@ -0,0 +1,36 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class GlassBlock extends TransparentBlock{
public function __construct(){
parent::__construct(GLASS, 0, "Glass");
}
public function getDrops(Item $item, Player $player){
return array();
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class GlassPaneBlock extends TransparentBlock{
public function __construct(){
parent::__construct(GLASS_PANE, 0, "Glass Pane");
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class GlowingObsidianBlock extends SolidBlock{
public function __construct($meta = 0){
parent::__construct(GLOWING_OBSIDIAN, $meta, "Glowing Obsidian");
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class GlowstoneBlock extends SolidBlock{
public function __construct(){
parent::__construct(GLOWSTONE_BLOCK, 0, "Glowstone");
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class GoldBlock extends SolidBlock{
public function __construct(){
parent::__construct(GOLD_BLOCK, 0, "Gold Block");
}
}

View File

@ -0,0 +1,67 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class GrassBlock extends SolidBlock{
public function __construct(){
parent::__construct(GRASS, 0, "Grass");
$this->isActivable = true;
}
public function getDrops(Item $item, Player $player){
return array(
array(DIRT, 0, 1),
);
}
public function onActivate(BlockAPI $level, Item $item, Player $player){
if($item->getID() === DYE and $item->getMetadata() === 0x0F){
for($c = 0; $c < 15; ++$c){
$x = mt_rand($this->x - 2, $this->x + 2);
$z = mt_rand($this->z - 2, $this->z + 2);
$b = $level->getBlock(new Vector3($x, $this->y + 1, $z));
$d = $level->getBlock(new Vector3($x, $this->y, $z));
if($b->getID() === AIR and $d->getID() === GRASS){
$arr = array(
array(DANDELION, 0),
array(CYAN_FLOWER, 0),
array(TALL_GRASS, 1),
array(TALL_GRASS, 1),
array(TALL_GRASS, 1),
array(TALL_GRASS, 1),
array(AIR, 0),
);
$t = $arr[mt_rand(0, count($arr) - 1)];
$level->setBlock($b, $t[0], $t[1]);
}
}
return true;
}elseif($item->isHoe()){
$level->setBlock($this, FARMLAND, 0);
return true;
}
return false;
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class GravelBlock extends FallableBlock{
public function __construct(){
parent::__construct(GRAVEL, 0, "Gravel");
}
}

View File

@ -25,12 +25,9 @@ the Free Software Foundation, either version 3 of the License, or
*/
class TileEntity extends stdClass{
private $server;
function __construct(PocketMinecraftServer $server){
class IceBlock extends TransparentBlock{
public function __construct(){
parent::__construct(ICE, 0, "Ice");
}
}
?>
}

View File

@ -0,0 +1,33 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class IronBlock extends SolidBlock{
public function __construct(){
parent::__construct(IRON_BLOCK, 0, "Iron Block");
}
}

View File

@ -0,0 +1,38 @@
<?php
/*
-
/ \
/ \
/ PocketMine \
/ MP \
|\ @shoghicp /|
|. \ / .|
| .. \ / .. |
| .. | .. |
| .. | .. |
\ | /
\ | /
\ | /
\ | /
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.
*/
class IronDoorBlock extends DoorBlock{
public function __construct($meta = 0){
parent::__construct(IRON_DOOR_BLOCK, $meta, "Iron Door Block");
//$this->isActivable = true;
}
public function getDrops(Item $item, Player $player){
return array(
array(IRON_DOOR, 0, 1),
);
}
}

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