Compare commits

..

262 Commits

Author SHA1 Message Date
b6025e3f2b Removed selectors on Player->sendMessage() 2014-10-06 16:45:11 +02:00
35de331b74 Fixed Level->getCollidingEntities() when called with a null Entity 2014-10-06 13:18:05 +02:00
de11cce154 Improved entity ticking 2014-10-06 13:10:59 +02:00
d53ba52d32 Removed parse errors from AutoReporting 2014-10-06 12:12:54 +02:00
9db2fe40eb Fixed player datta not getting saved, use fall distance on fly calculation 2014-10-06 12:02:36 +02:00
57bb8f14fa Fixed Player movement collision checks 2014-10-06 11:47:28 +02:00
761cd59514 Implemented flying protection 2014-10-06 11:22:59 +02:00
4c2a1c8684 Implement crop growth levels properly, fixes #2002, closes #2160 2014-10-06 09:34:40 +02:00
31bb6d1a68 Changed base block classes to abstract, closes #2159 2014-10-06 09:27:44 +02:00
cd65179aef Fixes #2155 2014-10-06 12:07:48 +10:30
9abd2c63f4 Improved initial chunk loading, do not skip near chunks, fixes world loading getting stuck 2014-10-06 00:45:02 +02:00
376e359577 Moved connected flag up in the Player disconnect process 2014-10-05 22:51:20 +02:00
571e2f8895 Revert "Option to disable hitbox calculation"
This reverts commit fae330d499.
2014-10-05 16:32:49 +02:00
7106ea87e6 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-10-05 16:32:27 +02:00
6b65b68ebc Possible fix for #1661 2014-10-05 16:32:15 +02:00
d4c75ce68a Trim system timezone output 2014-10-05 17:40:17 +10:30
fae330d499 Option to disable hitbox calculation 2014-10-04 20:07:37 -05:00
5e03e157ad Fixed #2153 2014-10-04 23:16:35 +02:00
b0c40dc1ab Fixed Server->unloadLevel() not removing objects from memory 2014-10-04 20:56:27 +02:00
6840589f4e Fix trailing newline 2014-10-04 18:28:42 +02:00
19e4aaa16a Merge pull request #2151 from sekjun9878/master
Timezone for Windows and IP Geolocation TZdata
2014-10-05 01:51:44 +09:30
e0a7944faa Re-use timezone offset parsing 2014-10-05 01:43:33 +09:30
eeda22d0ba Add portable linux timezone detection for incompatible linux distributions. 2014-10-05 01:29:07 +09:30
769f1effb0 Cleaner timezone parsing for Linux and add support for Macs 2014-10-05 01:05:00 +09:30
42c7322273 Reliable timezone detection using systeminfo for Windows and additional IP Geolocation-based detection. Added a warning message for when auto-detection fails. Fixes #2015. 2014-10-05 00:32:01 +09:30
c8cf6b715e Merge pull request #2150 from PEMapModder/patch-2
Fixed PlayerChatEvent::setRecipients() being ignored
2014-10-04 14:49:14 +02:00
41f94f7385 Fixed PlayerChatEvent::setRecipients() being useless 2014-10-04 20:10:12 +08:00
602bdf27a5 Compatibility with pthreads > 2.0.8 2014-10-02 16:58:37 +02:00
539fa232f8 Added individual object timings to Entities / Tile Entities 2014-09-30 16:09:21 +02:00
f8378c09ba Fixed entities getting OnGround default to true 2014-09-30 13:13:31 +02:00
69fb7ae525 Update RakLib, fixes server locking when shutting down 2014-09-30 09:52:50 +02:00
ee8ad6f92a Implement Armor changes as Transactions 2014-09-30 09:37:58 +02:00
f888acbd7c Send PlayerArmorEquipmentPacket instead of ContainerSetContentPacket with id 0x78 2014-09-29 23:43:52 +02:00
215691f1c4 Update RakLib 2014-09-29 23:23:11 +02:00
1252dd65a9 Improved PlayerInventory->setItemInHand() $source call, fixed Tool durability 2014-09-29 17:53:53 +02:00
762c27affe Added armor change $source parameter 2014-09-29 17:50:48 +02:00
706e1099a1 Update raklib 2014-09-29 16:46:19 +02:00
9cd66dc969 Some changes 2014-09-29 16:37:56 +02:00
5b6b789ab3 Improved exponentiation 2014-09-29 13:24:25 +02:00
85ff696ae5 Improved Chunk entity loading 2014-09-29 13:14:14 +02:00
25f8e8318b Fixed Anvil levels duplicating saved entities 2014-09-29 13:09:13 +02:00
61d84c73d0 Implemented Arrow pick up 2014-09-29 13:05:18 +02:00
f5822c6de8 Improved entity movement updates 2014-09-29 12:59:01 +02:00
b0bd927545 Improved entity base ticks 2014-09-29 12:55:10 +02:00
fde61b7d21 Improved single-threaded chunk generation efficiency 2014-09-29 12:48:11 +02:00
886ad8442c Fixed #2055 Extra packet data sent on armor change 2014-09-28 17:31:44 +02:00
7b5869bea8 RakLib submodule update 2014-09-28 16:35:24 +02:00
3063863c65 RakLib update 2014-09-28 16:06:27 +02:00
0dfaa19380 Fixed invalid spawn position setting for plugins 2014-09-28 15:19:09 +02:00
7fea29e874 Updated pthreads version on Travis-CI 2014-09-28 12:50:03 +02:00
2ded2013bf Fixed auto-save configuration, made it global 2014-09-28 10:50:43 +02:00
aa27c28e65 Force new player position on spawn 2014-09-28 01:14:03 +02:00
05a81bebf4 Fixed server crash when Tile Entities / Entities were loaded and requested the same chunk 2014-09-28 00:39:49 +02:00
ce91f2943a Fixed Double Chests 2014-09-28 00:39:11 +02:00
1d8562fb8c Allow setting the player spawnpoint via events before PlayerJoinEvent 2014-09-28 00:14:08 +02:00
1dfb17b932 Fixed #2126 Items drop twice from tile entities 2014-09-27 14:31:41 +02:00
16384c2b20 Improved Player generation queue 2014-09-27 10:31:02 +02:00
48041b2f19 Basic entity motion on water 2014-09-27 00:09:38 +02:00
529bf743db Added torch drop 2014-09-26 23:07:43 +02:00
48bc919a33 Added Liquid flow 2014-09-26 16:56:10 +02:00
474091c013 Improved Level block update scheduling for repeated updates 2014-09-26 16:55:34 +02:00
666e5553c2 Fixed Level->scheduleUpdate() tick calculation 2014-09-26 16:04:51 +02:00
ae6f532b1d Partial Liquid flow 2014-09-26 13:25:52 +02:00
b231eba803 Fixed E_NOTICE error on player movement 2014-09-26 13:23:47 +02:00
82d903733d Fixed #2121 2014-09-26 11:34:06 +02:00
8e2903da86 API version 1.4.1 2014-09-26 11:19:30 +02:00
d720113ac9 Added non-threaded chunk generation, toggleable on pocketmine.yml 2014-09-26 11:18:46 +02:00
5db45222c6 Deprecated Level->getChunkAt() in favor of Level->getChunk() 2014-09-26 10:31:32 +02:00
2975509d0f Improved chunk unload queue, possible fix for #1661 2014-09-25 23:03:56 +02:00
7e49d073fa Improved player movement, check once per tick 2014-09-24 16:58:22 +02:00
ef3674a296 Possible fix for #1661 2014-09-24 16:47:53 +02:00
6cb7e36f8a Improved knockback motion 2014-09-24 16:17:04 +02:00
b88f19bb74 Improved Level::getSafeSpawn() 2014-09-23 20:16:16 +02:00
8c3fcf0798 Send player metadata on respawn 2014-09-23 20:14:01 +02:00
6b312a7826 Fixed players getting Suffocation damage inside transparent blocks 2014-09-23 19:50:44 +02:00
9907e84eee Torches can now be crafted using charcoal 2014-09-23 19:36:30 +02:00
01f299a7f1 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-09-23 15:54:59 +02:00
91f20f6789 Add valid position difference back to Player entities 2014-09-23 15:54:48 +02:00
4c1edc3f7e Re-order RFC section 2014-09-23 20:32:39 +09:30
5fd1e271c5 Merge pull request #2112 from PocketMine/rfc-rfc-and-voting
RFC and Voting
2014-09-22 15:46:03 +02:00
593b0497b0 Fixed #1750 cannot place slabs against blocks 2014-09-22 11:58:15 +02:00
0907aedcef Fixed Entity/Block issues on negative coordinates, closes #2100 2014-09-22 11:48:39 +02:00
0a29e66b62 Fixed #2114 Removed Player collisions with other entities 2014-09-22 11:26:12 +02:00
3cc4afbcd6 Possible fix for #1920 2014-09-22 11:21:54 +02:00
b3ae6eae04 Added RFC ready status, added new label to label list 2014-09-22 09:30:14 +02:00
3b56b536b6 Changed RFC label 2014-09-22 08:46:03 +02:00
9258281546 Fixed missing whitespace 2014-09-21 21:18:37 +02:00
e7897be7cd Merge pull request #2113 from tnpxxsheepdog/rfc-rfc-and-voting
Update CONTRIBUTING.md
2014-09-21 21:08:18 +02:00
5ff01de413 Update CONTRIBUTING.md
Smoothed out wording, fix grammar.
2014-09-21 15:05:08 -04:00
f191ada405 Fixed text typo 2014-09-21 18:33:34 +02:00
addd74d09e Fix typo, added PR: Request for Comments label 2014-09-21 17:51:35 +02:00
4e9d2d0a7f Added 'RFC and Voting' to CONTRIBUTING.md 2014-09-21 17:45:58 +02:00
d04e994d1b Added TPS load to /status 2014-09-21 12:18:51 +02:00
3d870629f2 Fixed ifconfig command typo 2014-09-21 12:18:26 +02:00
8dbe834dc3 Submodule update 2014-09-21 12:18:10 +02:00
36d8100e17 Protect against \0 attacks on name checking 2014-09-20 18:26:17 +02:00
b880bf13f8 Documented tool usage in Level::useBreakOn() 2014-09-20 18:25:53 +02:00
1ac08ce404 Fixed Utils::getUniqueID() on Linux due to /proc/cpuinfo 2014-09-20 12:39:57 +02:00
689b2ea877 Fixed #2104 Can't place blocks where non-solid entities exist 2014-09-20 11:10:46 +02:00
d1f22ee395 Block more player actions when dead, closes #2102 2014-09-19 20:19:27 +02:00
056ed4802f Send project name on usage 2014-09-19 15:08:40 +02:00
bcb65e9a48 Send build number on usage 2014-09-19 15:07:48 +02:00
5404ba77d0 Throw exception when Server::dispatchCommand() is called with an invalid CommandSender 2014-09-19 10:30:35 +02:00
ae54426836 Fixed date_default_timezone_set E_NOTICE 2014-09-19 10:26:44 +02:00
ee7d84dfbd Fixed T_DOUBLE_COLON 2014-09-19 09:48:02 +02:00
3e1ea23036 Fixed CallbackTask name 2014-09-19 09:46:38 +02:00
d312d2a143 Possible fix for #2046, removed embedded class names 2014-09-19 09:44:58 +02:00
8c627bd0af Remove level locks, possible fix for #2046 2014-09-18 11:44:16 +02:00
6fb7170556 Handle force parameter properly on Level::unload() 2014-09-18 11:38:03 +02:00
50f5c6d8ed RakLib patches 2014-09-18 09:22:52 +02:00
f9d5c5bd37 Improved event checking on PlayerInteractEvent 2014-09-16 17:49:44 +02:00
45dbb3f828 Improved block collision check 2014-09-16 12:02:33 +02:00
8a8a95480e Added Cactus damage 2014-09-16 12:02:18 +02:00
34139c7efe Added more death messages 2014-09-16 11:51:43 +02:00
f0e7713dce Added suffocation, drowning damage. Closes #1908 2014-09-16 11:51:31 +02:00
3ba099b309 Cobweb, Ladders and Water won't cause fall damage 2014-09-16 10:52:00 +02:00
c4a0c759dc Show fire to other clients 2014-09-16 10:48:56 +02:00
e9a2f88847 Added Fire, Lava damage 2014-09-16 10:42:29 +02:00
e608acbd1c Improved Player last damage check 2014-09-16 10:42:01 +02:00
42033da08b Fixed #2035 Invalid Fence Gate bounding box 2014-09-16 00:47:04 +02:00
69ab0d433b Removed old trigger_error() 2014-09-16 00:42:36 +02:00
44a30b7fac Added forced position strong check for Player 2014-09-16 00:32:03 +02:00
50b2f55583 Increased movement error range 2014-09-15 23:53:08 +02:00
da084d6908 Fixed door bounding boxes, closes#2075 2014-09-15 23:40:26 +02:00
7d51bc0004 Possible fix for #2077 2014-09-15 22:14:05 +02:00
87dbc18452 Removed position revert message on plugin event cancelled 2014-09-15 20:32:42 +02:00
5b8d4bba11 Fixed issues with placing doors 2014-09-15 20:32:27 +02:00
bb4c54106a Added temporal workaround for pthreads version check 2014-09-15 18:55:15 +02:00
1617b2509e Fixed plugin-related crash 2014-09-15 12:09:30 +02:00
ec293ebd9e Merge pull request #2071 from PocketMine/pthreads-fix
Removed pthreads workarounds, new pthreads version
2014-09-15 10:16:35 +02:00
9f9422f0ed Added Player->forceMovement check on teleport 2014-09-15 01:16:13 +02:00
da715e48e2 Bumped pthreads version 2014-09-13 12:07:04 +02:00
702b2e539c Update RakLib 2014-09-13 12:01:11 +02:00
63fc229c12 Enabled default PHP GC on generator thread 2014-09-12 15:57:02 +02:00
c71689a919 Optimized server sleep times 2014-09-12 15:56:21 +02:00
09428bc8c7 Merge branch 'master' into pthreads-fix 2014-09-12 13:32:53 +02:00
6c7e16d9d4 Added Permission/Permissible calculation timings 2014-09-12 13:08:59 +02:00
315ea2ea3c 64-bit Random optimizations 2014-09-12 12:58:21 +02:00
83eb9f778a Level generators can be set in server.properties 2014-09-12 01:05:32 +02:00
7923c40b33 Removed as Vector3 on Flat generator 2014-09-12 00:12:52 +02:00
d298adabad Merge branch 'master' into pthreads-fix 2014-09-11 22:06:10 +02:00
cfcf515f62 Added type hint to BlockEvent::getBlock() 2014-09-11 21:57:56 +02:00
b5deae7ba0 Added synchronization to GenerationThread::pushMainToThreadPacket() 2014-09-11 19:18:14 +02:00
d991c32435 Fixed Generator Thread as specified on krakjoe/pthreads#349 2014-09-11 19:10:25 +02:00
dbd1f3f96e Use pthreads interface on Chunk Generation THread, remove IPC sockets, improve performance 2014-09-11 18:05:14 +02:00
0bd7ab9def Added .mailmap file, fixes duplicated commiter names 2014-09-11 17:41:07 +02:00
665c275bb7 New improved RakLib version with pthreads changes 2014-09-11 17:18:54 +02:00
7ef2708fca Permission & interface optimization 2014-09-11 16:43:11 +02:00
78b4223795 Added PermissionAttachment::unsetPermissions(), PermissionAttachment::clearPermissions() 2014-09-11 12:43:53 +02:00
0328b4c5f5 Added PermissionAttachment::setPermissions()
This allows bulk permission without recalculating the new permissions until all everything is set. Permission plugins that set a big amount of nodes may want to use this method.
2014-09-11 12:39:01 +02:00
4624dfb472 Fixed Permissible::setPermission() not using the correct order on replacement 2014-09-11 12:17:03 +02:00
fba12c6ddf Fixed EntityMoveEvent not being cancelled correctly on players 2014-09-10 20:06:30 +02:00
60011a5ecf Fixed PermissionAttachment not recalculating its Permissible permissions 2014-09-10 20:05:41 +02:00
f4ae58dda2 Removed pthreads workarounds 2014-09-10 15:11:56 +02:00
8c939feed9 Added Pumpkin & Lit Pumpkin rotation, closes 2014-09-10 12:36:05 +02:00
02ca227085 Normalized Player pitch/yaw 2014-09-10 12:23:23 +02:00
1174b0c45c Added binary reading optimizations, faster 64-bit reading 2014-09-10 12:13:15 +02:00
8940360df4 Possible fix for #2061 2014-09-10 10:43:24 +02:00
bb34e06754 Fix division by zero when the server goes too fast 2014-09-09 19:13:35 +02:00
e06092cb99 Added Server::getTickUsage() 2014-09-09 18:46:20 +02:00
57373b8c5e TPS measurement improvement, moved interface handling to tick 2014-09-09 18:07:27 +02:00
317c6788a6 Updated RakLib path 2014-09-08 10:11:43 +02:00
0a4e0e3228 Fixed Item drop delay 2014-09-08 07:40:19 +02:00
d8c492de4a Merge pull request #2062 from Yosshi999/patch1
Fixed HeldItem were swapped in mining
2014-09-08 07:37:24 +02:00
05d59d587b Merge pull request #2063 from Yosshi999/patch2
Fixed Player's slot[0] disappears on loging in
2014-09-08 07:37:16 +02:00
7d387fe6aa Fixed TravisTest output 2014-09-07 19:54:13 +02:00
4f7a6a06be Fixed TravisTest pipes 2014-09-07 19:47:31 +02:00
344c84cfa6 Added --disable-readline CLI argument 2014-09-07 19:42:36 +02:00
bd721a13a3 Merge branch 'master' of github.com:PocketMine/PocketMine-MP 2014-09-07 19:33:01 +02:00
92b0b4d43c Implemented basic Travis-CI test 2014-09-07 19:32:21 +02:00
d0b0fbf992 Merge pull request #2064 from PEMapModder/patch-2
Fixed wrong cases
2014-09-07 09:02:54 +02:00
ab334e6962 Fixed wrong cases
I know this doesn't matter at all, but it is ugly in IDEs.
2014-09-07 13:21:05 +08:00
1ad6438e60 Fixed Player's slot[0] disappears on loging in 2014-09-07 11:37:54 +09:00
4ecec42c9d Fixed HeldItem were swapped in mining 2014-09-07 11:29:17 +09:00
84e62598ce Implemented attack cooldown 2014-09-06 16:52:52 +02:00
ad7acb93b6 Added cactus neighbour block check 2014-09-05 11:16:24 +02:00
ac4b4b08fd Fixed Level::setBlock() old calls 2014-09-05 11:00:13 +02:00
d3c308c5a8 Fixed possible Player crash on save 2014-09-05 10:50:19 +02:00
98e0583f34 Implemented Falling Sand 2014-09-05 10:50:06 +02:00
020351e20f Fixed #2052 2014-09-05 09:02:45 +02:00
f140fef52d Possible fix for level save issues, related to #1985 #1982 #1758 2014-09-04 12:37:27 +02:00
9980a0780a Fixed Server::getTicksPerSecond() 2014-09-04 12:22:16 +02:00
352497d88c Improves server ticking.
As I was lying in my bed, I came to a solution for the tick problem.
While remembering how most of the time the server is sleeping,
and how the TPS drops once costly operations are ticked,
I reviewed mentally that part of the code, Server::tick().

Then I saw it: I was setting the next execution time
using the time after it was executed as the base, but it should
have been done using the tick start time - that way if something takes
longer, the server will catch up and won't drop the TPS
until the CPU hits its limit.

I got up, got to my computer, and checked that function.
It was exactly as I saw in a near-dream state, so I fixed it
and tested things if they worked right.

Now I'm fully awake and I can't sleep anymore, so I wrote this.
2014-09-04 01:04:09 +02:00
ba08bfaa45 Do not report E_PARSE or E_COMPILE_ERROR crashes 2014-09-03 13:38:24 +02:00
dea4513c34 Possible fix for #2041 2014-09-03 11:55:49 +02:00
0eac084aa7 Added extra documentation to Level::setBlock() 2014-09-03 11:44:30 +02:00
e17ecf5795 Improved Arrow / Item movement 2014-09-03 10:55:14 +02:00
e94ddcabe0 Fixed dropped items going too fast 2014-09-01 23:37:31 +02:00
acf7eb1ce9 Remove scheduled updates from entities 2014-09-01 23:30:35 +02:00
dcfb7a7ac4 Fixed #2037 2014-09-01 17:47:28 +02:00
97c87aa8fa Added __debugInfo() to Server and Level 2014-09-01 17:37:28 +02:00
11f684d803 Improved CallbackTask timings data 2014-09-01 12:44:52 +02:00
ff48eb3d4d Added better Entity/Tile scheduled updates 2014-09-01 11:59:46 +02:00
e047b6a870 Fixed bows not getting damaged 2014-09-01 11:43:48 +02:00
c5626bae34 Do not set Level to null, closes #2032 2014-09-01 11:29:44 +02:00
3eac08f5ba Possible fix for #2027, properly check Player onGround flag 2014-09-01 02:32:16 +02:00
cc2555bb88 Fixed crash when chests are closed with viewers 2014-09-01 02:26:23 +02:00
705e4da789 Tick entities on Level, show correct timing reports 2014-09-01 01:56:13 +02:00
9b7a94b5ee Fixed timings ticks getting reset 2014-09-01 01:50:28 +02:00
bcdb6d8c2e Fixed timings name 2014-09-01 01:28:42 +02:00
eff63a661e Player creative check refactor 2014-08-31 10:49:20 +02:00
5a756d215d Fixed creative players dropping their inventory 2014-08-31 10:45:38 +02:00
422262d585 Fixed infinite Entity recursion on chunk load 2014-08-31 01:06:53 +02:00
b761a97660 Fixed crash due to class name conflict 2014-08-31 01:05:15 +02:00
7579cd763a Added Trapdoor bounding box 2014-08-30 23:57:57 +02:00
6bc5f60011 Added Cobble Wall bounding box 2014-08-30 23:52:06 +02:00
3eb8ca0d13 Added Soul Sand bounding box 2014-08-30 23:47:39 +02:00
a23352be88 Added Ladder bounding box 2014-08-30 23:45:08 +02:00
fa5f00a1ff Added Cake bounding boxe 2014-08-30 23:42:07 +02:00
d3a05adede Added Doors bounding boxes 2014-08-30 23:38:56 +02:00
f9182bd0f8 Added Iron bars bounding box 2014-08-30 23:30:10 +02:00
edad52c6ea Added Glass Pane bounding box 2014-08-30 23:30:01 +02:00
cd5e16f017 Added Fence Gate bounding box 2014-08-30 23:20:59 +02:00
310a7d6c04 Added Fence bounding box 2014-08-30 23:18:37 +02:00
ccea26c978 Added Farmland bounding box 2014-08-30 23:07:55 +02:00
cf542ac73a Added End Portal frame bounding box 2014-08-30 23:06:50 +02:00
3bf39df255 Added cactus bounding box 2014-08-30 23:06:27 +02:00
910e5e6181 Added stairs bounding box 2014-08-30 23:01:33 +02:00
a396b8c220 Fixed #2021 2014-08-30 21:45:32 +02:00
ec1fe6a083 Fixed EntityShootBowEventEvent crash 2014-08-30 19:07:17 +02:00
706c97b9b1 Made shooting bow use its durability 2014-08-30 18:46:09 +02:00
a04516a879 Added EntityShootBowEvent, made bow require an arrow 2014-08-30 18:43:32 +02:00
0f6dfd39b8 Made EntityDamageByEntityEvent call EntityDamageEvent handlers 2014-08-30 18:41:00 +02:00
36ee6d9966 Added arrow and suicide death messages 2014-08-30 18:30:39 +02:00
23793e0fc4 Added check for invalid entity attack 2014-08-30 18:24:24 +02:00
3409d332e7 Added survival check to movements 2014-08-30 17:57:30 +02:00
ca1b67a675 hmm 2014-08-30 17:07:50 +02:00
f5eed4f12b Disable RakLib port checking by default 2014-08-30 16:14:09 +02:00
7a10f91330 Fixed entity partial block moving 2014-08-30 15:31:22 +02:00
6477f4f077 Added Wooden Slab bounding box 2014-08-30 02:14:48 +02:00
3731e74696 Added Slab bounding box 2014-08-30 02:14:24 +02:00
c774e4c203 Added Carpet bounding box 2014-08-30 02:09:15 +02:00
d4907a2688 Added Chest bounding box 2014-08-30 02:07:50 +02:00
793520926b Added Bed bounding box 2014-08-30 02:06:46 +02:00
bf839e821c Added proper arrows and damage 2014-08-30 01:22:46 +02:00
7aeacf2705 Fixed armor crafting recipes 2014-08-29 14:49:41 +02:00
fc62c91c90 Fixed double physics calculation 2014-08-29 13:33:59 +02:00
98dd7f8c15 Use Entity::move() as player movement, protect against noclip cheat 2014-08-29 13:33:25 +02:00
7a1d25617f Fixed physics sneak flag 2014-08-29 13:02:08 +02:00
69b3ef326b Merge pull request #1994 from PocketMine/nbt-array
Added NBT <-> PHP array/type conversion methods
2014-08-29 12:17:10 +02:00
fadff2cc5b Removed debug code 2014-08-28 23:59:18 +02:00
43a0ef433e API version bump 2014-08-28 23:44:19 +02:00
9a1e7ca83c Implemented NBT::getArray() and NBT::setArray() 2014-08-28 23:43:04 +02:00
b9111b6f52 Fixed #1992 2014-08-28 23:19:44 +02:00
be70121f3a Renamed Item\Block to Item\ItemBlock 2014-08-28 22:28:32 +02:00
e2986992c7 Fixed AxisAlignedBB infinite expansion 2014-08-28 21:11:49 +02:00
9fb46d8fe8 Fixed entity physics 2014-08-28 18:26:37 +02:00
eab86f5f90 Replaced array() with [] 2014-08-28 17:04:22 +02:00
2f2afe2336 Fixed #1966 Face Lit Pumkins correctly 2014-08-28 11:00:41 +02:00
f7de1ede3f Made PocketMine loader backwards-compatible 2014-08-27 21:30:36 +02:00
812ae09a06 Merge branch 'php-5.6' 2014-08-27 21:24:52 +02:00
e473cd5e67 Improved unloaded tile entity handling 2014-08-27 18:18:33 +02:00
9e5e4fb362 Fixed possible Level::getBlock() crash 2014-08-27 18:11:23 +02:00
afa98866e0 Fixed Item after-clone behaviour 2014-08-27 18:11:02 +02:00
90fa40de34 Added entity id names 2014-08-27 17:42:38 +02:00
e6234c4c4d Removed cli_set_process_title() check 2014-08-27 12:45:14 +02:00
8f66d03d99 Improved Item::get() 2014-08-27 12:43:54 +02:00
8e9da9c84e Improved safe_var_dump(), Inventory::addItem() Inventory::removeItem() using argument unpacking 2014-08-27 12:29:04 +02:00
759d7e2545 Initial PHP 5.6 features support 2014-08-27 12:21:01 +02:00
f4b92bcdfc Fixed #1980 2014-08-27 11:41:00 +02:00
f7e2d31f0a Check player online status, closes #1983 2014-08-27 11:28:49 +02:00
e0fc3784ad Throw exception when saving an already-closed player, closes #1981 2014-08-26 22:02:43 +02:00
237 changed files with 5090 additions and 2327 deletions

5
.mailmap Normal file
View File

@ -0,0 +1,5 @@
Shoghi Cervantes <shoghicp@gmail.com>
Shoghi Cervantes <shoghicp@gmail.com> Shoghi Cervantes <shoghicp@pocketmine.net>
Brandon V <brandon15811@gmail.com>
Michael Yoo <sekjun9878@gmail.com> Michael Yoo <michael@yoo.id.au>
Michael Yoo <sekjun9878@gmail.com> Michael Yoo <sekjun9878@sekjun9878.info>

View File

@ -1,23 +1,21 @@
language: php
php:
- 5.4
- 5.5
- 5.6
branches:
except:
- Core-Rewrite
- master
- 0.9.0
- master
before_script:
- pecl install channel://pecl.php.net/pthreads-2.0.4
- mkdir plugins
- wget -O plugins/DevTools.phar https://github.com/PocketMine/DevTools/releases/download/v1.9.0/DevTools_v1.9.0.phar
- pecl install channel://pecl.php.net/pthreads-2.0.10
- pecl install channel://pecl.php.net/weakref-0.2.4
- echo | pecl install channel://pecl.php.net/yaml-1.1.1
script:
- php src/tests/ServerSuiteTest.php --no-wizard
- php tests/TravisTest.php
notifications:
email: false
webhooks: http://n.tkte.ch/h/214/wsNvmG43-ncxUVRrFPwSM-r0
#webhooks: http://n.tkte.ch/h/214/wsNvmG43-ncxUVRrFPwSM-r0

View File

@ -72,6 +72,19 @@ class ExampleClass{
}
```
### RFC and Voting
* These are big Pull Requests or contributions that change important behavior.
* RFCs will be tagged with the *PR: RFC* label
* A vote will be held once the RFC is ready. All users can vote commenting on the Pull Request
* Comments MUST use "Yes" or "No" on the FIRST sentence to signify the vote, except when they don't want it to be counted.
* If your comment is a voting comment, specify the reason of your vote or it won't be counted.
* After voting has been closed, no further votes will be counted.
* An RFC will be rejected if less than 50% + 1 (simple majority) has voted Yes.
* If the RFC is approved, Team Members have the final word on its implementation or rejection.
* RFCs with complex voting options will specify the vote percentage or other details.
## Bug Tracking for Collaborators
### Labels
@ -91,6 +104,7 @@ Category labels are prefixed by `C:`. Multiple category labels may be applied to
Pull Requests are prefixed by `PR:`. Only one label may be applied for a Pull Request.
- PR: Bug Fix - This label is applied when the Pull Request fixes a bug.
- PR: Contribution - This label is applied when the Pull Request contributes code to PocketMine-MP such as a new feature or an improvement.
- PR: RFC - Request for Comments
#### Status
Status labels show the status of the issue. Multiple status labels may be applied.

View File

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

View File

@ -22,6 +22,7 @@
namespace pocketmine;
use pocketmine\network\protocol\Info;
use pocketmine\plugin\PluginBase;
use pocketmine\plugin\PluginLoadOrder;
use pocketmine\utils\Utils;
use pocketmine\utils\VersionString;
@ -137,7 +138,7 @@ class CrashDump{
}else{
$error = (array) error_get_last();
$error["trace"] = getTrace(4);
$errorConversion = array(
$errorConversion = [
E_ERROR => "E_ERROR",
E_WARNING => "E_WARNING",
E_PARSE => "E_PARSE",
@ -153,7 +154,7 @@ class CrashDump{
E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
E_DEPRECATED => "E_DEPRECATED",
E_USER_DEPRECATED => "E_USER_DEPRECATED",
);
];
$error["fullFile"] = $error["file"];
$error["file"] = cleanPath($error["file"]);
$error["type"] = isset($errorConversion[$error["type"]]) ? $errorConversion[$error["type"]] : $error["type"];
@ -179,7 +180,7 @@ class CrashDump{
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
$this->data["plugin"] = true;
$reflection = new \ReflectionClass("pocketmine\\plugin\\PluginBase");
$reflection = new \ReflectionClass(PluginBase::class);
$file = $reflection->getProperty("file");
$file->setAccessible(true);
foreach($this->server->getPluginManager()->getPlugins() as $plugin){
@ -228,7 +229,7 @@ class CrashDump{
$this->data["general"]["zend"] = zend_version();
$this->data["general"]["php_os"] = PHP_OS;
$this->data["general"]["os"] = Utils::getOS();
$this->addLine("PocketMine-MP version: " . $version->get(false) . " #" . $version->getNumber() . " [Protocol " . Info::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
$this->addLine("PocketMine-MP version: " . $version->get(false) . " #" . $version->getBuild() . " [Protocol " . Info::CURRENT_PROTOCOL . "; API " . API_VERSION . "]");
$this->addLine("Git commit: " . GIT_COMMIT);
$this->addLine("uname -a: " . php_uname("a"));
$this->addLine("PHP Version: " . phpversion());

File diff suppressed because it is too large Load Diff

View File

@ -73,10 +73,17 @@ namespace pocketmine {
use raklib\RakLib;
const VERSION = "Alpha_1.4dev";
const API_VERSION = "1.3.1";
const API_VERSION = "1.4.1";
const CODENAME = "絶好(Zekkou)ケーキ(Cake)";
const MINECRAFT_VERSION = "v0.9.5 alpha";
/*
* Startup code. Do not look at it, it may harm you.
* Most of them are hacks to fix date-related bugs, or basic functions used after this
* This is the only non-class based file on this project.
* Enjoy it as much as I did writing it. I don't want to do it again.
*/
if(\Phar::running(true) !== ""){
@define("pocketmine\\PATH", \Phar::running(true) . "/");
}else{
@ -98,46 +105,12 @@ namespace pocketmine {
$autoloader = new CompatibleClassLoader();
$autoloader->addPath(\pocketmine\PATH . "src");
$autoloader->addPath(\pocketmine\PATH . "src" . DIRECTORY_SEPARATOR . "spl");
$autoloader->addPath(\pocketmine\PATH . "src" . DIRECTORY_SEPARATOR . "raklib");
$autoloader->register(true);
if(!class_exists("raklib\\RakLib", false)){
require(\pocketmine\PATH . "src/raklib/raklib/RakLib.php");
}
RakLib::bootstrap($autoloader);
//Startup code. Do not look at it, it can harm you. Most of them are hacks to fix date-related bugs, or basic functions used after this
set_time_limit(0); //Who set it to 30 seconds?!?!
if(ini_get("date.timezone") == ""){ //No Timezone set
date_default_timezone_set("GMT");
if(strpos(" " . strtoupper(php_uname("s")), " WIN") !== false){
$time = time();
$time -= $time % 60;
//TODO: Parse different time & date formats by region. ¬¬ world
//Example: USA
@exec("time.exe /T", $hour);
$i = array_map("intval", explode(":", trim($hour[0])));
@exec("date.exe /T", $date);
$j = array_map("intval", explode(substr($date[0], 2, 1), trim($date[0])));
$offset = @round((mktime($i[0], $i[1], 0, $j[1], $j[0], $j[2]) - $time) / 60) * 60;
}else{
@exec("date +%s", $t);
$offset = @round((intval(trim($t[0])) - time()) / 60) * 60;
}
$daylight = (int) date("I");
$d = timezone_name_from_abbr("", $offset, $daylight);
@ini_set("date.timezone", $d);
date_default_timezone_set($d);
}else{
$d = @date_default_timezone_get();
if(strpos($d, "/") === false){
$d = timezone_name_from_abbr($d);
@ini_set("date.timezone", $d);
date_default_timezone_set($d);
}
}
gc_enable();
error_reporting(-1);
ini_set("allow_url_fopen", 1);
@ -148,15 +121,158 @@ namespace pocketmine {
ini_set("memory_limit", "256M"); //Default
define("pocketmine\\START_TIME", microtime(true));
$opts = getopt("", array("enable-ansi", "disable-ansi", "data:", "plugins:", "no-wizard", "enable-profiler"));
$opts = getopt("", ["enable-ansi", "disable-ansi", "data:", "plugins:", "no-wizard", "enable-profiler"]);
define("pocketmine\\DATA", isset($opts["data"]) ? realpath($opts["data"]) . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR);
define("pocketmine\\PLUGIN_PATH", isset($opts["plugins"]) ? realpath($opts["plugins"]) . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
define("pocketmine\\ANSI", ((strpos(strtoupper(php_uname("s")), "WIN") === false or isset($opts["enable-ansi"])) and !isset($opts["disable-ansi"])));
//Logger has a dependency on timezone, so we'll set it to UTC until we can get the actual timezone.
date_default_timezone_set("UTC");
$logger = new MainLogger(\pocketmine\DATA . "server.log", \pocketmine\ANSI);
if(!ini_get("date.timezone")){
if(($timezone = detect_system_timezone()) and date_default_timezone_set($timezone)){
//Success! Timezone has already been set and validated in the if statement.
//This here is just for redundancy just in case some stupid program wants to read timezone data from the ini.
ini_set("date.timezone", $timezone);
}else{
//If system timezone detection fails or timezone is an invalid value.
if($response = Utils::getURL("http://ip-api.com/json")
and $ip_geolocation_data = json_decode($response, true)
and $ip_geolocation_data['status'] != 'fail'
and date_default_timezone_set($ip_geolocation_data['timezone']))
{
//Again, for redundancy.
ini_set("date.timezone", $ip_geolocation_data['timezone']);
}else{
ini_set("date.timezone", "UTC");
date_default_timezone_set("UTC");
$logger->warning("Timezone could not be automatically determined. An incorrect timezone will result in incorrect timestamps on console logs. It has been set to \"UTC\" by default. You can change it on the php.ini file.");
}
}
}else{
/*
* This is here so that stupid idiots don't come to us complaining and fill up the issue tracker when they put an incorrect timezone abbreviation in php.ini apparently.
*/
$default_timezone = date_default_timezone_get();
if(strpos($default_timezone, "/") === false){
$default_timezone = timezone_name_from_abbr($default_timezone);
ini_set("date.timezone", $default_timezone);
date_default_timezone_set($default_timezone);
}
}
function detect_system_timezone(){
switch(Utils::getOS()){
case 'win':
$regex = '/(?:Time Zone:\s*\()(UTC)(\+*\-*\d*\d*\:*\d*\d*)(?:\))/';
exec("systeminfo", $output);
$string = trim(implode("\n", $output));
//Detect the Time Zone string in systeminfo
preg_match($regex, $string, $matches);
if(!isset($matches[2]))
{
return false;
}
$offset = $matches[2];
if($offset == ""){
return "UTC";
}
return parse_offset($offset);
break;
case 'linux':
// Ubuntu / Debian.
if(file_exists('/etc/timezone')){
$data = file_get_contents('/etc/timezone');
if($data){
return trim($data);
}
}
// RHEL / CentOS
if(file_exists('/etc/sysconfig/clock')){
$data = parse_ini_file('/etc/sysconfig/clock');
if(!empty($data['ZONE'])){
return trim($data['ZONE']);
}
}
//Portable method for incompatible linux distributions.
$offset = trim(exec('date +%:z'));
if($offset == "+00:00"){
return "UTC";
}
return parse_offset($offset);
break;
case 'mac':
if(is_link('/etc/localtime')){
$filename = readlink('/etc/localtime');
if(strpos($filename, '/usr/share/zoneinfo/') === 0){
$timezone = substr($filename, 20);
return trim($timezone);
}
}
return false;
break;
default:
return false;
break;
}
}
/**
* @param string $offset In the format of +09:00, +02:00, -04:00 etc.
* @return string
*/
function parse_offset($offset){
//Make signed offsets unsigned for date_parse
if(strpos($offset, '-') !== false){
$negative_offset = true;
$offset = str_replace('-', '', $offset);
}else{
if(strpos($offset, '+') !== false){
$negative_offset = false;
$offset = str_replace('+', '', $offset);
}else{
return false;
}
}
$parsed = date_parse($offset);
$offset = $parsed['hour'] * 3600 + $parsed['minute'] * 60 + $parsed['second'];
//After date_parse is done, put the sign back
if($negative_offset == true){
$offset = -abs($offset);
}
//And then, look the offset up.
//timezone_name_from_abbr is not used because it returns false on some(most) offsets because it's mapping function is weird.
//That's been a bug in PHP since 2008!
foreach(timezone_abbreviations_list() as $zones){
foreach($zones as $timezone){
if($timezone['offset'] == $offset){
return $timezone['timezone_id'];
}
}
}
return false;
}
if(isset($opts["enable-profiler"])){
if(function_exists("profiler_enable")){
\profiler_enable();
@ -217,7 +333,7 @@ namespace pocketmine {
if(error_reporting() === 0){ //@ error-control
return false;
}
$errorConversion = array(
$errorConversion = [
E_ERROR => "E_ERROR",
E_WARNING => "E_WARNING",
E_PARSE => "E_PARSE",
@ -233,7 +349,7 @@ namespace pocketmine {
E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
E_DEPRECATED => "E_DEPRECATED",
E_USER_DEPRECATED => "E_USER_DEPRECATED",
);
];
$type = ($errno === E_ERROR or $errno === E_WARNING or $errno === E_USER_ERROR or $errno === E_USER_WARNING) ? LogLevel::ERROR : LogLevel::NOTICE;
$errno = isset($errorConversion[$errno]) ? $errorConversion[$errno] : $errno;
if(($pos = strpos($errstr, "\n")) !== false){
@ -263,8 +379,8 @@ namespace pocketmine {
$errors = 0;
if(version_compare("5.5.0", PHP_VERSION) > 0){
$logger->critical("Use PHP >= 5.5.0");
if(version_compare("5.6.0", PHP_VERSION) > 0){
$logger->critical("You must use PHP >= 5.6");
++$errors;
}
@ -282,8 +398,8 @@ namespace pocketmine {
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
if(version_compare($pthreads_version, "2.0.4") < 0){
$logger->critical("pthreads >= 2.0.4 is required, while you have $pthreads_version.");
if(version_compare($pthreads_version, "2.0.8") < 0){
$logger->critical("pthreads >= 2.0.8 is required, while you have $pthreads_version.");
++$errors;
}

View File

@ -42,9 +42,14 @@ use pocketmine\inventory\CraftingManager;
use pocketmine\inventory\InventoryType;
use pocketmine\inventory\Recipe;
use pocketmine\item\Item;
use pocketmine\level\format\anvil\Anvil;
use pocketmine\level\format\LevelProviderManager;
use pocketmine\level\format\mcregion\McRegion;
use pocketmine\level\generator\Flat;
use pocketmine\level\generator\GenerationInstanceManager;
use pocketmine\level\generator\GenerationRequestManager;
use pocketmine\level\generator\Generator;
use pocketmine\level\generator\Normal;
use pocketmine\level\Level;
use pocketmine\metadata\EntityMetadataStore;
use pocketmine\metadata\LevelMetadataStore;
@ -61,7 +66,6 @@ use pocketmine\nbt\tag\Short;
use pocketmine\nbt\tag\String;
use pocketmine\network\protocol\DataPacket;
use pocketmine\network\query\QueryHandler;
use pocketmine\network\query\QueryPacket;
use pocketmine\network\RakLibInterface;
use pocketmine\network\rcon\RCON;
use pocketmine\network\SourceInterface;
@ -78,6 +82,7 @@ use pocketmine\scheduler\ServerScheduler;
use pocketmine\tile\Tile;
use pocketmine\updater\AutoUpdater;
use pocketmine\utils\Binary;
use pocketmine\utils\Cache;
use pocketmine\utils\Config;
use pocketmine\utils\MainLogger;
use pocketmine\utils\TextFormat;
@ -128,15 +133,15 @@ class Server{
*/
private $tickCounter;
private $nextTick = 0;
private $tickMeasure = 20;
private $tickTime = 0;
private $inTick = false;
private $tickAverage = [20,20,20,20,20];
private $useAverage = [20,20,20,20,20];
/** @var \AttachableThreadedLogger */
private $logger;
/** @var CommandReader */
private $console = null;
private $consoleThreaded;
/** @var SimpleCommandMap */
private $commandMap = null;
@ -150,6 +155,9 @@ class Server{
/** @var int */
private $maxPlayers;
/** @var bool */
private $autoSave;
/** @var RCON */
private $rcon;
@ -292,6 +300,23 @@ class Server{
return $this->getConfigString("server-name", "Unknown server");
}
/**
* @return bool
*/
public function getAutoSave(){
return $this->autoSave;
}
/**
* @param bool $value
*/
public function setAutoSave($value){
$this->autoSave = (bool) $value;
foreach($this->getLevels() as $level){
$level->setAutoSave($this->autoSave);
}
}
/**
* @return string
*/
@ -537,7 +562,16 @@ class Server{
* @return float
*/
public function getTicksPerSecond(){
return round((0.05 / $this->tickMeasure) * 20, 2);
return round(array_sum($this->tickAverage) / count($this->tickAverage), 2);
}
/**
* Returns the TPS usage/load in %
*
* @return float
*/
public function getTickUsage(){
return round((array_sum($this->useAverage) / count($this->useAverage)) * 100, 2);
}
/**
@ -626,14 +660,14 @@ class Server{
$path = $this->getDataPath() . "players/";
if(!file_exists($path . "$name.dat")){
$spawn = $this->getDefaultLevel()->getSafeSpawn();
$nbt = new Compound(false, array(
$nbt = new Compound(false, [
new Long("firstPlayed", floor(microtime(true) * 1000)),
new Long("lastPlayed", floor(microtime(true) * 1000)),
new Enum("Pos", array(
new Enum("Pos", [
new Double(0, $spawn->x),
new Double(1, $spawn->y),
new Double(2, $spawn->z)
)),
]),
new String("Level", $this->getDefaultLevel()->getName()),
//new String("SpawnLevel", $this->getDefaultLevel()->getName()),
//new Int("SpawnX", (int) $spawn->x),
@ -643,22 +677,22 @@ class Server{
new Enum("Inventory", []),
new Compound("Achievements", []),
new Int("playerGameType", $this->getGamemode()),
new Enum("Motion", array(
new Enum("Motion", [
new Double(0, 0.0),
new Double(1, 0.0),
new Double(2, 0.0)
)),
new Enum("Rotation", array(
]),
new Enum("Rotation", [
new Float(0, 0.0),
new Float(1, 0.0)
)),
]),
new Float("FallDistance", 0.0),
new Short("Fire", 0),
new Short("Air", 0),
new Byte("OnGround", 1),
new Byte("Invulnerable", 0),
new String("NameTag", $name),
));
]);
$nbt->Pos->setTagType(NBT::TAG_Double);
$nbt->Inventory->setTagType(NBT::TAG_Compound);
$nbt->Motion->setTagType(NBT::TAG_Double);
@ -678,35 +712,35 @@ class Server{
$this->logger->notice("Old Player data found for \"" . $name . "\", upgrading profile");
foreach($data->get("inventory") as $slot => $item){
if(count($item) === 3){
$nbt->Inventory[$slot + 9] = new Compound(false, array(
$nbt->Inventory[$slot + 9] = new Compound(false, [
new Short("id", $item[0]),
new Short("Damage", $item[1]),
new Byte("Count", $item[2]),
new Byte("Slot", $slot + 9),
new Byte("TrueSlot", $slot + 9)
));
]);
}
}
foreach($data->get("hotbar") as $slot => $itemSlot){
if(isset($nbt->Inventory[$itemSlot + 9])){
$item = $nbt->Inventory[$itemSlot + 9];
$nbt->Inventory[$slot] = new Compound(false, array(
$nbt->Inventory[$slot] = new Compound(false, [
new Short("id", $item["id"]),
new Short("Damage", $item["Damage"]),
new Byte("Count", $item["Count"]),
new Byte("Slot", $slot),
new Byte("TrueSlot", $item["TrueSlot"])
));
]);
}
}
foreach($data->get("armor") as $slot => $item){
if(count($item) === 2){
$nbt->Inventory[$slot + 100] = new Compound(false, array(
$nbt->Inventory[$slot + 100] = new Compound(false, [
new Short("id", $item[0]),
new Short("Damage", $item[1]),
new Byte("Count", 1),
new Byte("Slot", $slot + 100)
));
]);
}
}
foreach($data->get("achievements") as $achievement => $status){
@ -788,7 +822,7 @@ class Server{
$matchedPlayers = [];
foreach($this->getOnlinePlayers() as $player){
if(strtolower($player->getName()) === $partialName){
$matchedPlayers = array($player);
$matchedPlayers = [$player];
break;
}elseif(stripos($player->getName(), $partialName) !== false){
$matchedPlayers[] = $player;
@ -802,7 +836,12 @@ class Server{
* @param Player $player
*/
public function removePlayer(Player $player){
unset($this->players[$player->getAddress() . ":" . $player->getPort()]);
foreach($this->players as $identifier => $p){
if($player === $p){
unset($this->players[$identifier]);
break;
}
}
}
/**
@ -876,7 +915,7 @@ class Server{
* @return bool
*/
public function unloadLevel(Level $level, $forceUnload = false){
if($level->unload($forceUnload) === true and $this->isLevelLoaded($level->getFolderName())){
if($level->unload($forceUnload) === true){
unset($this->levels[$level->getID()]);
return true;
@ -930,6 +969,8 @@ class Server{
$this->levels[$level->getID()] = $level;
$level->initLevel();
$this->getPluginManager()->callEvent(new LevelLoadEvent($level));
/*foreach($entities->getAll() as $entity){
@ -1045,15 +1086,11 @@ class Server{
$seed = $seed === null ? Binary::readInt(Utils::getRandomBytes(4, false)) : (int) $seed;
if($generator !== null and class_exists($generator) and is_subclass_of($generator, "pocketmine\\level\\generator\\Generator")){
if($generator !== null and class_exists($generator) and is_subclass_of($generator, Generator::class)){
$generator = new $generator($options);
}else{
if(strtoupper($this->getLevelType()) == "FLAT"){
$generator = Generator::getGenerator("flat");
$options["preset"] = $this->getConfigString("generator-settings", "");
}else{
$generator = Generator::getGenerator("normal");
}
$options["preset"] = $this->getConfigString("generator-settings", "");
$generator = Generator::getGenerator($this->getLevelType());
}
if(($provider = LevelProviderManager::getProviderByName($providerName = $this->getProperty("level-settings.default-format", "mcregion"))) === null){
@ -1067,6 +1104,8 @@ class Server{
$level = new Level($this, $name, $path, $provider);
$this->levels[$level->getID()] = $level;
$level->initLevel();
$this->getPluginManager()->callEvent(new LevelInitEvent($level));
$this->getPluginManager()->callEvent(new LevelLoadEvent($level));
@ -1084,7 +1123,7 @@ class Server{
for($X = -$radius; $X <= $radius; ++$X){
for($Z = -$radius; $Z <= $radius; ++$Z){
$distance = ($X * $X) + ($Z * $Z);
$distance = $X ** 2 + $Z ** 2;
if($distance > $radiusSquared){
continue;
}
@ -1142,7 +1181,7 @@ class Server{
* @return string
*/
public function getConfigString($variable, $defaultValue = ""){
$v = getopt("", array("$variable::"));
$v = getopt("", ["$variable::"]);
if(isset($v[$variable])){
return (string) $v[$variable];
}
@ -1192,7 +1231,7 @@ class Server{
* @return int
*/
public function getConfigInt($variable, $defaultValue = 0){
$v = getopt("", array("$variable::"));
$v = getopt("", ["$variable::"]);
if(isset($v[$variable])){
return (int) $v[$variable];
}
@ -1215,7 +1254,7 @@ class Server{
* @return boolean
*/
public function getConfigBoolean($variable, $defaultValue = false){
$v = getopt("", array("$variable::"));
$v = getopt("", ["$variable::"]);
if(isset($v[$variable])){
$value = $v[$variable];
}else{
@ -1411,7 +1450,8 @@ class Server{
$this->banByIP = new BanList($this->dataPath . "banned-ips.txt");
$this->banByIP->load();
$this->console = new CommandReader();
$this->consoleThreaded = new \Threaded();
$this->console = new CommandReader($this->consoleThreaded);
$version = new VersionString($this->getPocketMineVersion());
$this->logger->info("Starting Minecraft: PE server version " . TextFormat::AQUA . $this->getVersion());
@ -1427,7 +1467,7 @@ class Server{
$this->config = new Config($this->dataPath . "pocketmine.yml", Config::YAML, []);
$this->logger->info("Loading server properties...");
$this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, array(
$this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, [
"motd" => "Minecraft: PE Server",
"server-port" => 19132,
"memory-limit" => "256M",
@ -1451,7 +1491,7 @@ class Server{
"enable-rcon" => false,
"rcon.password" => substr(base64_encode(Utils::getRandomBytes(20, false)), 3, 10),
"auto-save" => true,
));
]);
ServerScheduler::$WORKERS = $this->getProperty("settings.async-workers", ServerScheduler::$WORKERS);
@ -1462,9 +1502,10 @@ class Server{
}
$this->maxPlayers = $this->getConfigInt("max-players", 20);
$this->setAutoSave($this->getConfigBoolean("auto-save", true));
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "256M")))) !== false){
$value = array("M" => 1, "G" => 1024);
$value = ["M" => 1, "G" => 1024];
$real = ((int) substr($memory, 0, -1)) * $value[substr($memory, -1)];
if($real < 128){
$this->logger->warning($this->getName() . " may not work right with less than 128MB of RAM", true, true, 0);
@ -1487,9 +1528,9 @@ class Server{
$this->logger->info("Advanced cache enabled");
}
Level::$COMPRESSION_LEVEL = $this->getProperty("chunk-sending.compression-level", 7);
Level::$COMPRESSION_LEVEL = $this->getProperty("chunk-sending.compression-level", 8);
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0 and function_exists("cli_set_process_title")){
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0){
@cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion());
}
@ -1502,6 +1543,9 @@ class Server{
$this->logger->info("This server is running " . $this->getName() . " version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(false) . TextFormat::RESET . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0);
$this->logger->info($this->getName() . " is distributed under the LGPL License", true, true, 0);
PluginManager::$pluginParentTimer = new TimingsHandler("** Plugins");
Timings::init();
$this->consoleSender = new ConsoleCommandSender();
$this->commandMap = new SimpleCommandMap($this);
@ -1510,13 +1554,10 @@ class Server{
Item::init();
$this->craftingManager = new CraftingManager();
PluginManager::$pluginParentTimer = new TimingsHandler("** Plugins");
Timings::init();
$this->pluginManager = new PluginManager($this, $this->commandMap);
$this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender);
$this->pluginManager->setUseTimings($this->getProperty("settings.enable-profiling", false));
$this->pluginManager->registerInterface("pocketmine\\plugin\\PharPluginLoader");
$this->pluginManager->registerInterface(PharPluginLoader::class);
set_exception_handler([$this, "exceptionHandler"]);
register_shutdown_function([$this, "crashDump"]);
@ -1528,15 +1569,26 @@ class Server{
$this->enablePlugins(PluginLoadOrder::STARTUP);
$this->generationManager = new GenerationRequestManager($this);
if($this->getProperty("chunk-generation.use-async", true)){
$this->generationManager = new GenerationRequestManager($this);
}else{
$this->generationManager = new GenerationInstanceManager($this);
}
LevelProviderManager::addProvider($this, "pocketmine\\level\\format\\anvil\\Anvil");
LevelProviderManager::addProvider($this, "pocketmine\\level\\format\\mcregion\\McRegion");
LevelProviderManager::addProvider($this, Anvil::class);
LevelProviderManager::addProvider($this, McRegion::class);
Generator::addGenerator("pocketmine\\level\\generator\\Flat", "flat");
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "normal");
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "default");
Generator::addGenerator(Flat::class, "flat");
Generator::addGenerator(Normal::class, "normal");
Generator::addGenerator(Normal::class, "default");
//Temporal workaround, pthreads static property nullification test
if(PluginManager::$pluginParentTimer === null){
$this->getLogger()->emergency("You are using an invalid pthreads version. Please update your binaries.");
kill(getmypid());
return;
}
foreach($this->getProperty("worlds", []) as $name => $worldSetting){
if($this->loadLevel($name) === false){
@ -1558,7 +1610,7 @@ class Server{
if($this->getDefaultLevel() === null){
$default = $this->getConfigString("level-name", "world");
if(trim($default) == ""){
trigger_error("level-name cannot be null, using default", E_USER_WARNING);
$this->getLogger()->warning("level-name cannot be null, using default");
$default = "world";
$this->setConfigString("level-name", "world");
}
@ -1580,9 +1632,9 @@ class Server{
return;
}
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask("pocketmine\\utils\\Cache::cleanup"), $this->getProperty("ticks-per.cache-cleanup", 900), $this->getProperty("ticks-per.cache-cleanup", 900));
if($this->getConfigBoolean("auto-save", true) === true and $this->getProperty("ticks-per.autosave", 6000) > 0){
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "doAutoSave")), $this->getProperty("ticks-per.autosave", 6000), $this->getProperty("ticks-per.autosave", 6000));
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([Cache::class, "cleanup"]), $this->getProperty("ticks-per.cache-cleanup", 900), $this->getProperty("ticks-per.cache-cleanup", 900));
if($this->getAutoSave() and $this->getProperty("ticks-per.autosave", 6000) > 0){
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([$this, "doAutoSave"]), $this->getProperty("ticks-per.autosave", 6000), $this->getProperty("ticks-per.autosave", 6000));
}
if($this->getProperty("chunk-gc.period-in-ticks", 600) > 0){
@ -1596,11 +1648,17 @@ class Server{
/**
* @param $message
* @param Player[]|null $recipients
*
* @return int
*/
public function broadcastMessage($message){
return $this->broadcast($message, self::BROADCAST_CHANNEL_USERS);
public function broadcastMessage($message, $recipients = null){
if(!is_array($recipients)){
return $this->broadcast($message, self::BROADCAST_CHANNEL_USERS);
}
foreach($recipients as $recipient){
$recipient->sendMessage($message);
}
}
/**
@ -1694,8 +1752,14 @@ class Server{
* @param string $commandLine
*
* @return bool
*
* @throws \Exception
*/
public function dispatchCommand(CommandSender $sender, $commandLine){
if(!($sender instanceof CommandSender)){
throw new \Exception("CommandSender is not valid");
}
if($this->commandMap->dispatch($sender, $commandLine)){
return true;
}
@ -1725,7 +1789,7 @@ class Server{
$this->maxPlayers = $this->getConfigInt("max-players", 20);
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "256M")))) !== false){
$value = array("M" => 1, "G" => 1024);
$value = ["M" => 1, "G" => 1024];
$real = ((int) substr($memory, 0, -1)) * $value[substr($memory, -1)];
if($real < 256){
$this->logger->warning($this->getName() . " may not work right with less than 256MB of RAM", true, true, 0);
@ -1745,7 +1809,7 @@ class Server{
$this->operators->reload();
$this->pluginManager->registerInterface("pocketmine\\plugin\\PharPluginLoader");
$this->pluginManager->registerInterface(PharPluginLoader::class);
$this->pluginManager->loadPlugins($this->pluginPath);
$this->enablePlugins(PluginLoadOrder::STARTUP);
$this->enablePlugins(PluginLoadOrder::POSTWORLD);
@ -1809,7 +1873,7 @@ class Server{
if($this->getProperty("settings.send-usage", true) !== false){
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "sendUsage")), 6000, 6000);
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([$this, "sendUsage"]), 6000, 6000);
$this->sendUsage();
}
@ -1828,7 +1892,10 @@ class Server{
$this->getScheduler()->scheduleRepeatingTask(new CallbackTask("pcntl_signal_dispatch"), 5);
}
$this->logger->info("Default game type: " . self::getGamemodeString($this->getGamemode())); //TODO: string name
$this->getScheduler()->scheduleRepeatingTask(new CallbackTask([$this, "checkTicks"]), 20 * 5);
$this->logger->info("Default game type: " . self::getGamemodeString($this->getGamemode()));
$this->logger->info("Done (" . round(microtime(true) - \pocketmine\START_TIME, 3) . 's)! For help, type "help" or "?"');
@ -1894,7 +1961,8 @@ class Server{
}
}elseif(\Phar::running(true) == ""){
return;
}elseif($dump->getData()["type"] === "E_PARSE" or $dump->getData()["type"] === "E_COMPILE_ERROR"){
}
if($dump->getData()["error"]["type"] === "E_PARSE" or $dump->getData()["error"]["type"] === "E_COMPILE_ERROR"){
return;
}
@ -1917,31 +1985,15 @@ class Server{
}
public function __debugInfo(){
return get_class($this);
}
private function tickProcessor(){
$lastLoop = 0;
$connectionTimer = Timings::$connectionTimer;
while($this->isRunning){
$connectionTimer->startTiming();
foreach($this->interfaces as $interface){
if($interface->process()){
$lastLoop = 0;
}
}
$connectionTimer->stopTiming();
$this->generationManager->handlePackets();
++$lastLoop;
if(($ticks = $this->tick()) !== true){
if($lastLoop > 2 and $lastLoop < 16){
usleep(1000);
}elseif($lastLoop < 128){
usleep(2000);
}else{
usleep(10000);
}
}
$this->tick();
usleep((int) max(1, ($this->nextTick - microtime(true)) * 1000000));
}
}
@ -1951,32 +2003,6 @@ class Server{
private function checkTickUpdates($currentTick){
//TODO: move this to each Level
//Update entities that need update
if(count(Entity::$needUpdate) > 0){
Timings::$tickEntityTimer->startTiming();
foreach(Entity::$needUpdate as $id => $entity){
if($entity->onUpdate() === false){
unset(Entity::$needUpdate[$id]);
}
}
Timings::$tickEntityTimer->stopTiming();
}
//Update tiles that need update
if(count(Tile::$needUpdate) > 0){
Timings::$tickTileEntityTimer->startTiming();
foreach(Tile::$needUpdate as $id => $tile){
if($tile->onUpdate() === false){
unset(Tile::$needUpdate[$id]);
}
}
Timings::$tickTileEntityTimer->stopTiming();
}
//TODO: Add level blocks
//Do level ticks
foreach($this->getLevels() as $level){
$level->doTick($currentTick);
@ -1984,16 +2010,21 @@ class Server{
}
public function doAutoSave(){
if($this->getAutoSave()){
Timings::$worldSaveTimer->startTiming();
foreach($this->getOnlinePlayers() as $index => $player){
if($player->isOnline()){
$player->save();
}elseif(!$player->isConnected()){
unset($this->players[$index]);
}
}
Timings::$worldSaveTimer->startTiming();
foreach($this->getOnlinePlayers() as $player){
$player->save();
foreach($this->getLevels() as $level){
$level->save(false);
}
Timings::$worldSaveTimer->stopTiming();
}
foreach($this->getLevels() as $level){
$level->save(false);
}
Timings::$worldSaveTimer->stopTiming();
}
public function doLevelGC(){
@ -2008,35 +2039,37 @@ class Server{
return;
}
}
$plist = "";
foreach($this->getPluginManager()->getPlugins() as $p){
$d = $p->getDescription();
$plist .= str_replace(array(";", ":"), "", $d->getName()) . ":" . str_replace(array(";", ":"), "", $d->getVersion()) . ";";
$plist .= str_replace([";", ":"], "", $d->getName()) . ":" . str_replace([";", ":"], "", $d->getVersion()) . ";";
}
$version = new VersionString();
$this->lastSendUsage = new SendUsageTask("http://stats.pocketmine.net/usage.php", array(
"serverid" => Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() . ":" . $this->getPort()), 0, 8)),
$this->lastSendUsage = new SendUsageTask("http://stats.pocketmine.net/usage.php", [
"serverid" => $this->serverID,
"port" => $this->getPort(),
"os" => Utils::getOS(),
"name" => $this->getName(),
"memory_total" => $this->getConfigString("memory-limit"),
"memory_usage" => memory_get_usage(),
"php_version" => PHP_VERSION,
"version" => $version->get(false),
"version" => $version->get(true),
"build" => $version->getBuild(),
"mc_version" => \pocketmine\MINECRAFT_VERSION,
"protocol" => network\protocol\Info::CURRENT_PROTOCOL,
"online" => count($this->players),
"max" => $this->getMaxPlayers(),
"plugins" => $plist,
));
]);
$this->scheduler->scheduleAsyncTask($this->lastSendUsage);
}
private function titleTick(){
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0 and \pocketmine\ANSI === true){
echo "\x1b]0;". $this->getName() . " " . $this->getPocketMineVersion() . " | Online " . count($this->players) . "/" . $this->getMaxPlayers() . " | RAM " . round((memory_get_usage() / 1024) / 1024, 2) . "/" . round((memory_get_usage(true) / 1024) / 1024, 2) . " MB | U " . round($this->mainInterface->getUploadUsage() / 1024, 2) . " D " . round($this->mainInterface->getDownloadUsage() / 1024, 2) . " kB/s | TPS " . $this->getTicksPerSecond() . "\x07";
echo "\x1b]0;". $this->getName() . " " . $this->getPocketMineVersion() . " | Online " . count($this->players) . "/" . $this->getMaxPlayers() . " | RAM " . round((memory_get_usage() / 1024) / 1024, 2) . "/" . round((memory_get_usage(true) / 1024) / 1024, 2) . " MB | U " . round($this->mainInterface->getUploadUsage() / 1024, 2) . " D " . round($this->mainInterface->getDownloadUsage() / 1024, 2) . " kB/s | TPS " . $this->getTicksPerSecond() . " | Load ". $this->getTickUsage() . "%\x07";
}
}
@ -2044,44 +2077,56 @@ class Server{
/**
* Tries to execute a server tick
*/
public function tick(){
if($this->inTick === false){
$tickTime = microtime(true);
if($tickTime < $this->nextTick){
return false;
}
Timings::$serverTickTimer->startTiming();
$this->inTick = true; //Fix race conditions
++$this->tickCounter;
$this->checkConsole();
Timings::$schedulerTimer->startTiming();
$this->scheduler->mainThreadHeartbeat($this->tickCounter);
Timings::$schedulerTimer->stopTiming();
$this->checkTickUpdates($this->tickCounter);
if(($this->tickCounter & 0b1111) === 0){
$this->titleTick();
if(isset($this->queryHandler) and ($this->tickCounter & 0b111111111) === 0){
$this->queryHandler->regenerateInfo();
}
}
TimingsHandler::tick();
$this->tickMeasure = (($time = microtime(true)) - $this->tickTime);
$this->tickTime = $time;
$this->nextTick = 0.05 * (0.05 / max(0.05, $this->tickMeasure)) + $time;
$this->inTick = false;
Timings::$serverTickTimer->stopTiming();
return true;
private function tick(){
$tickTime = microtime(true);
if($tickTime < $this->nextTick){
return false;
}
return false;
Timings::$serverTickTimer->startTiming();
++$this->tickCounter;
$this->checkConsole();
Timings::$connectionTimer->startTiming();
foreach($this->interfaces as $interface){
$interface->process();
}
Timings::$connectionTimer->stopTiming();
Timings::$schedulerTimer->startTiming();
$this->scheduler->mainThreadHeartbeat($this->tickCounter);
Timings::$schedulerTimer->stopTiming();
$this->checkTickUpdates($this->tickCounter);
if(($this->tickCounter & 0b1111) === 0){
$this->titleTick();
if(isset($this->queryHandler) and ($this->tickCounter & 0b111111111) === 0){
$this->queryHandler->regenerateInfo();
}
}
$this->generationManager->process();
Timings::$serverTickTimer->stopTiming();
TimingsHandler::tick();
$now = microtime(true);
array_shift($this->tickAverage);
$this->tickAverage[] = min(20, 1 / max(0.001, $now - $tickTime));
array_shift($this->useAverage);
$this->useAverage[] = min(1, ($now - $tickTime) / 0.05);
if(($this->nextTick - $tickTime) < -1){
$this->nextTick = $tickTime;
}
$this->nextTick += 0.05;
$this->inTick = false;
return true;
}
}

View File

@ -29,6 +29,6 @@ abstract class Thread extends \Thread{
public final function start($options = PTHREADS_INHERIT_ALL){
ThreadManager::getInstance()->add($this);
return parent::start($options & ~PTHREADS_INHERIT_CLASSES);
return parent::start($options);
}
}

View File

@ -29,6 +29,6 @@ abstract class Worker extends \Worker{
public final function start($options = PTHREADS_INHERIT_ALL){
ThreadManager::getInstance()->add($this);
return parent::start($options & ~PTHREADS_INHERIT_CLASSES);
return parent::start($options);
}
}

View File

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

View File

@ -23,6 +23,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\network\protocol\ChatPacket;
use pocketmine\Player;
@ -34,6 +35,17 @@ class Bed extends Transparent{
$this->hardness = 1;
}
public function getBoundingBox(){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + 1,
$this->y + 0.5625,
$this->z + 1
);
}
public function onActivate(Item $item, Player $player = null){
$time = $this->getLevel()->getTime() % Level::TIME_FULL;
@ -86,19 +98,19 @@ class Bed extends Transparent{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->isTransparent === false){
$faces = array(
$faces = [
0 => 3,
1 => 4,
2 => 2,
3 => 5,
);
];
$d = $player instanceof Player ? $player->getDirection() : 0;
$next = $this->getSide($faces[(($d + 3) % 4)]);
$downNext = $this->getSide(0);
if($next->isReplaceable === true and $downNext->isTransparent === false){
$meta = (($d + 3) % 4) & 0x03;
$this->getLevel()->setBlock($block, Block::get($this->id, $meta), true, false, true);
$this->getLevel()->setBlock($next, Block::get($this->id, $meta | 0x08), true, false, true);
$this->getLevel()->setBlock($block, Block::get($this->id, $meta), true, true);
$this->getLevel()->setBlock($next, Block::get($this->id, $meta | 0x08), true, true);
return true;
}
@ -115,34 +127,34 @@ class Bed extends Transparent{
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
$this->getLevel()->setBlock($blockNorth, new Air(), true, false, true);
$this->getLevel()->setBlock($blockNorth, new Air(), true, true);
}elseif($blockSouth->getID() === $this->id and $blockSouth->meta !== 0x08){
$this->getLevel()->setBlock($blockSouth, new Air(), true, false, true);
$this->getLevel()->setBlock($blockSouth, new Air(), true, true);
}elseif($blockEast->getID() === $this->id and $blockEast->meta !== 0x08){
$this->getLevel()->setBlock($blockEast, new Air(), true, false, true);
$this->getLevel()->setBlock($blockEast, new Air(), true, true);
}elseif($blockWest->getID() === $this->id and $blockWest->meta !== 0x08){
$this->getLevel()->setBlock($blockWest, new Air(), true, false, true);
$this->getLevel()->setBlock($blockWest, new Air(), true, true);
}
}else{ //Bottom Part of Bed
if($blockNorth->getID() === $this->id and ($blockNorth->meta & 0x08) === 0x08){
$this->getLevel()->setBlock($blockNorth, new Air(), true, false, true);
$this->getLevel()->setBlock($blockNorth, new Air(), true, true);
}elseif($blockSouth->getID() === $this->id and ($blockSouth->meta & 0x08) === 0x08){
$this->getLevel()->setBlock($blockSouth, new Air(), true, false, true);
$this->getLevel()->setBlock($blockSouth, new Air(), true, true);
}elseif($blockEast->getID() === $this->id and ($blockEast->meta & 0x08) === 0x08){
$this->getLevel()->setBlock($blockEast, new Air(), true, false, true);
$this->getLevel()->setBlock($blockEast, new Air(), true, true);
}elseif($blockWest->getID() === $this->id and ($blockWest->meta & 0x08) === 0x08){
$this->getLevel()->setBlock($blockWest, new Air(), true, false, true);
$this->getLevel()->setBlock($blockWest, new Air(), true, true);
}
}
$this->getLevel()->setBlock($this, new Air(), true, false, true);
$this->getLevel()->setBlock($this, new Air(), true, true);
return true;
}
public function getDrops(Item $item){
return array(
array(Item::BED, 0, 1),
);
return [
[Item::BED, 0, 1],
];
}
}

View File

@ -39,7 +39,7 @@ class Beetroot extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -49,8 +49,11 @@ class Beetroot extends Flowable{
public function onActivate(Item $item, Player $player = null){
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
$this->meta = 0x07;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->meta += mt_rand(2, 5);
if($this->meta > 7){
$this->meta = 7;
}
$this->getLevel()->setBlock($this, $this, true, true);
$item->count--;
return true;
@ -63,7 +66,7 @@ class Beetroot extends Flowable{
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent === true){ //TODO: Replace with common break method
$this->getLevel()->dropItem($this, Item::get(Item::BEETROOT_SEEDS, 0, 1));
$this->getLevel()->setBlock($this, new Air(), false, false, true);
$this->getLevel()->setBlock($this, new Air(), false);
return Level::BLOCK_UPDATE_NORMAL;
}
@ -71,7 +74,7 @@ class Beetroot extends Flowable{
if(mt_rand(0, 2) == 1){
if($this->meta < 0x07){
++$this->meta;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
return Level::BLOCK_UPDATE_RANDOM;
}
@ -86,10 +89,10 @@ class Beetroot extends Flowable{
public function getDrops(Item $item){
$drops = [];
if($this->meta >= 0x07){
$drops[] = array(Item::BEETROOT, 0, 1);
$drops[] = array(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3));
$drops[] = [Item::BEETROOT, 0, 1];
$drops[] = [Item::BEETROOT_SEEDS, 0, mt_rand(0, 3)];
}else{
$drops[] = array(Item::BEETROOT_SEEDS, 0, 1);
$drops[] = [Item::BEETROOT_SEEDS, 0, 1];
}
return $drops;

View File

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

View File

@ -24,12 +24,15 @@
*/
namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\entity\Villager;
use pocketmine\entity\Zombie;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\level\MovingObjectPosition;
use pocketmine\level\Position;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\metadata\Metadatable;
use pocketmine\metadata\MetadataValue;
use pocketmine\Player;
@ -230,7 +233,7 @@ abstract class Block extends Position implements Metadatable{
const GLOWING_OBSIDIAN = 246;
const NETHER_REACTOR = 247;
public static $creative = array(
public static $creative = [
//Building
[Item::COBBLESTONE, 0],
[Item::STONE_BRICKS, 0],
@ -500,7 +503,7 @@ abstract class Block extends Position implements Metadatable{
[Item::DYE, 9],
[Item::DYE, 8],
);
];
/** @var Block[] */
public static $list = [];
@ -526,7 +529,7 @@ abstract class Block extends Position implements Metadatable{
public static function init(){
if(count(self::$list) === 0){
self::$list = array(
self::$list = [
self::AIR => Air::class,
self::STONE => Stone::class,
self::GRASS => Grass::class,
@ -663,7 +666,7 @@ abstract class Block extends Position implements Metadatable{
self::STONECUTTER => Stonecutter::class,
self::GLOWING_OBSIDIAN => GlowingObsidian::class,
self::NETHER_REACTOR => NetherReactor::class,
);
];
}
}
@ -721,6 +724,10 @@ abstract class Block extends Position implements Metadatable{
return $this->id;
}
public function addVelocityToEntity(Entity $entity, Vector3 $vector){
}
/**
* @return int
*/
@ -759,7 +766,7 @@ abstract class Block extends Position implements Metadatable{
return [];
}else{
return [
array($this->id, $this->meta, 1),
[$this->id, $this->meta, 1],
];
}
}
@ -830,6 +837,13 @@ abstract class Block extends Position implements Metadatable{
}
}
/**
* @param Entity $entity
*/
public function onEntityCollide(Entity $entity){
}
/**
* @return AxisAlignedBB
*/
@ -844,6 +858,88 @@ abstract class Block extends Position implements Metadatable{
);
}
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2){
$bb = $this->getBoundingBox();
if($bb === null){
return null;
}
$v1 = $pos1->getIntermediateWithXValue($pos2, $bb->minX);
$v2 = $pos1->getIntermediateWithXValue($pos2, $bb->maxX);
$v3 = $pos1->getIntermediateWithYValue($pos2, $bb->minY);
$v4 = $pos1->getIntermediateWithYValue($pos2, $bb->maxY);
$v5 = $pos1->getIntermediateWithZValue($pos2, $bb->minZ);
$v6 = $pos1->getIntermediateWithZValue($pos2, $bb->maxZ);
if($v1 !== null and !$bb->isVectorInYZ($v1)){
$v1 = null;
}
if($v2 !== null and !$bb->isVectorInYZ($v2)){
$v2 = null;
}
if($v3 !== null and !$bb->isVectorInXZ($v3)){
$v3 = null;
}
if($v4 !== null and !$bb->isVectorInXZ($v4)){
$v4 = null;
}
if($v5 !== null and !$bb->isVectorInXY($v5)){
$v5 = null;
}
if($v6 !== null and !$bb->isVectorInXY($v6)){
$v6 = null;
}
$vector = $v1;
if($v2 !== null and ($vector === null or $pos1->distanceSquared($v2) < $pos1->distanceSquared($vector))){
$vector = $v2;
}
if($v3 !== null and ($vector === null or $pos1->distanceSquared($v3) < $pos1->distanceSquared($vector))){
$vector = $v3;
}
if($v4 !== null and ($vector === null or $pos1->distanceSquared($v4) < $pos1->distanceSquared($vector))){
$vector = $v4;
}
if($v5 !== null and ($vector === null or $pos1->distanceSquared($v5) < $pos1->distanceSquared($vector))){
$vector = $v5;
}
if($v6 !== null and ($vector === null or $pos1->distanceSquared($v6) < $pos1->distanceSquared($vector))){
$vector = $v6;
}
if($vector === null){
return null;
}
$f = -1;
if($vector === $v1){
$f = 4;
}elseif($vector === $v2){
$f = 5;
}elseif($vector === $v3){
$f = 0;
}elseif($vector === $v4){
$f = 1;
}elseif($vector === $v5){
$f = 2;
}elseif($vector === $v6){
$f = 3;
}
return MovingObjectPosition::fromBlock($this->x, $this->y, $this->z, $f, $vector->add($this->x, $this->y, $this->z));
}
/**
* Places the Block, using block space and block target, and side. Returns if the block has been placed.
*

View File

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

View File

@ -47,7 +47,7 @@ class BrownMushroom extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->isTransparent === false){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}

View File

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

View File

@ -23,8 +23,12 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3 as Vector3;
use pocketmine\Player;
use pocketmine\entity\Entity;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\Server;
class Cactus extends Transparent{
public function __construct($meta = 0){
@ -33,6 +37,25 @@ class Cactus extends Transparent{
$this->hardness = 2;
}
public function getBoundingBox(){
return new AxisAlignedBB(
$this->x + 0.0625,
$this->y,
$this->z + 0.0625,
$this->x + 0.9375,
$this->y + 1,
$this->z + 0.9375
);
}
public function onEntityCollide(Entity $entity){
$ev = new EntityDamageEvent($entity, EntityDamageEvent::CAUSE_CONTACT, 1);
Server::getInstance()->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$entity->attack($ev->getFinalDamage(), $ev);
}
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(0);
@ -40,7 +63,17 @@ class Cactus extends Transparent{
$this->getLevel()->setBlock($this, new Air(), false);
$this->getLevel()->dropItem($this, Item::get($this->id));
return Level::BLOCK_UPDATE_NORMAL;
return;
}else{
for($side = 2; $side <= 5; ++$side){
$b = $this->getSide($side);
if(!$b->isFlowable){
$this->getLevel()->setBlock($this, new Air(), false);
$this->getLevel()->dropItem($this, Item::get($this->id));
return;
}
}
}
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if($this->getSide(0)->getID() !== self::CACTUS){
@ -48,18 +81,18 @@ class Cactus extends Transparent{
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlock(new Vector3($this->x, $this->y + $y, $this->z));
if($b->getID() === self::AIR){
$this->getLevel()->setBlock($b, new Cactus(), true, false, true);
$this->getLevel()->setBlock($b, new Cactus(), true);
break;
}
}
$this->meta = 0;
$this->getLevel()->setBlock($this, $this, false);
$this->getLevel()->setBlock($this, $this);
}else{
++$this->meta;
$this->getLevel()->setBlock($this, $this, false);
$this->getLevel()->setBlock($this, $this);
}
return Level::BLOCK_UPDATE_RANDOM;
return;
}
}
@ -74,7 +107,7 @@ class Cactus extends Transparent{
$block2 = $this->getSide(4);
$block3 = $this->getSide(5);
if($block0->isTransparent === true and $block1->isTransparent === true and $block2->isTransparent === true and $block3->isTransparent === true){
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
return true;
}
@ -84,8 +117,8 @@ class Cactus extends Transparent{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
}

View File

@ -23,6 +23,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\Player;
class Cake extends Transparent{
@ -34,10 +35,23 @@ class Cake extends Transparent{
$this->hardness = 2.5;
}
public function getBoundingBox(){
$f = (1 + $this->getDamage() * 2) / 16;
return new AxisAlignedBB(
$this->x + $f,
$this->y,
$this->z + 0.0625,
$this->x + 1 - 0.0625,
$this->y + 0.5,
$this->z + 1 - 0.0625
);
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() !== self::AIR){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -48,7 +62,7 @@ class Cake extends Transparent{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->getID() === self::AIR){ //Replace with common break method
$this->getLevel()->setBlock($this, new Air(), true, false, true);
$this->getLevel()->setBlock($this, new Air(), true);
return Level::BLOCK_UPDATE_NORMAL;
}
@ -66,9 +80,9 @@ class Cake extends Transparent{
++$this->meta;
$player->heal(3, "cake");
if($this->meta >= 0x06){
$this->getLevel()->setBlock($this, new Air(), true, false, true);
$this->getLevel()->setBlock($this, new Air(), true);
}else{
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
}
return true;

View File

@ -23,12 +23,13 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\Player;
class Carpet extends Flowable{
public function __construct($meta = 0){
parent::__construct(self::CARPET, $meta, "Carpet");
$names = array(
$names = [
0 => "White Carpet",
1 => "Orange Carpet",
2 => "Magenta Carpet",
@ -45,17 +46,28 @@ class Carpet extends Flowable{
13 => "Green Carpet",
14 => "Red Carpet",
15 => "Black Carpet",
);
];
$this->name = $names[$this->meta];
$this->hardness = 0;
$this->isFullBlock = false;
$this->isSolid = true;
}
public function getBoundingBox(){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + 1,
$this->y + 0.0625,
$this->z + 1
);
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() !== self::AIR){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -67,7 +79,7 @@ class Carpet extends Flowable{
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->getID() === self::AIR){ //TODO: Replace with common break method
$this->getLevel()->dropItem($this, Item::get($this->id, $this->meta, 1));
$this->getLevel()->setBlock($this, new Air(), true, false, true);
$this->getLevel()->setBlock($this, new Air(), true);
return Level::BLOCK_UPDATE_NORMAL;
}

View File

@ -40,7 +40,7 @@ class Carrot extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -50,8 +50,11 @@ class Carrot extends Flowable{
public function onActivate(Item $item, Player $player = null){
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
$this->meta = 0x07;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->meta += mt_rand(2, 5);
if($this->meta > 7){
$this->meta = 7;
}
$this->getLevel()->setBlock($this, $this, true);
$item->count--;
return true;
@ -73,7 +76,7 @@ class Carrot extends Flowable{
if(mt_rand(0, 2) == 1){
if($this->meta < 0x07){
++$this->meta;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
return Level::BLOCK_UPDATE_RANDOM;
}
@ -88,9 +91,9 @@ class Carrot extends Flowable{
public function getDrops(Item $item){
$drops = [];
if($this->meta >= 0x07){
$drops[] = array(Item::CARROT, 0, mt_rand(1, 4));
$drops[] = [Item::CARROT, 0, mt_rand(1, 4)];
}else{
$drops[] = array(Item::CARROT, 0, 1);
$drops[] = [Item::CARROT, 0, 1];
}
return $drops;

View File

@ -22,6 +22,7 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\Enum;
@ -41,13 +42,24 @@ class Chest extends Transparent{
$this->hardness = 15;
}
public function getBoundingBox(){
return new AxisAlignedBB(
$this->x + 0.0625,
$this->y,
$this->z + 0.0625,
$this->x + 0.9375,
$this->y + 0.875,
$this->z + 0.9375
);
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$faces = array(
$faces = [
0 => 4,
1 => 2,
2 => 5,
3 => 3,
);
];
$chest = false;
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
@ -68,16 +80,16 @@ class Chest extends Transparent{
}
}
$this->getLevel()->setBlock($block, $this, true, false, true);
$nbt = new Compound(false, array(
$this->getLevel()->setBlock($block, $this, true, true);
$nbt = new Compound(false, [
new Enum("Items", []),
new String("id", Tile::CHEST),
new Int("x", $this->x),
new Int("y", $this->y),
new Int("z", $this->z)
));
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$tile = new TileChest($this->getLevel()->getChunkAt($this->x >> 4, $this->z >> 4), $nbt);
$tile = new TileChest($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
if($chest instanceof TileChest){
$chest->pairWith($tile);
@ -92,7 +104,7 @@ class Chest extends Transparent{
if($t instanceof TileChest){
$t->unpair();
}
$this->getLevel()->setBlock($this, new Air(), true, true, true);
$this->getLevel()->setBlock($this, new Air(), true, true);
return true;
}
@ -109,15 +121,15 @@ class Chest extends Transparent{
if($t instanceof TileChest){
$chest = $t;
}else{
$nbt = new Compound(false, array(
$nbt = new Compound(false, [
new Enum("Items", []),
new String("id", Tile::CHEST),
new Int("x", $this->x),
new Int("y", $this->y),
new Int("z", $this->z)
));
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$chest = new TileChest($this->getLevel()->getChunkAt($this->x >> 4, $this->z >> 4), $nbt);
$chest = new TileChest($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), $nbt);
}
@ -131,19 +143,8 @@ class Chest extends Transparent{
}
public function getDrops(Item $item){
$drops = array(
array($this->id, 0, 1),
);
$t = $this->getLevel()->getTile($this);
if($t instanceof TileChest){
for($s = 0; $s < $t->getRealInventory()->getSize(); ++$s){
$slot = $t->getRealInventory()->getItem($s);
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$drops[] = array($slot->getID(), $slot->getDamage(), $slot->getCount());
}
}
}
return $drops;
return [
[$this->id, 0, 1],
];
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -22,6 +22,7 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\entity\Entity;
class Cobweb extends Flowable{
public function __construct(){
@ -31,6 +32,10 @@ class Cobweb extends Flowable{
$this->hardness = 25;
}
public function onEntityCollide(Entity $entity){
$entity->fallDistance = 0;
}
public function getDrops(Item $item){
return [];
}

View File

@ -39,7 +39,7 @@ class CyanFlower extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === 2 or $down->getID() === 3 or $down->getID() === 60){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}

View File

@ -39,7 +39,7 @@ class Dandelion extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === 2 or $down->getID() === 3 or $down->getID() === 60){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}

View File

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

View File

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

View File

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

View File

@ -39,7 +39,7 @@ class Dirt extends Solid{
public function onActivate(Item $item, Player $player = null){
if($item->isHoe()){
$item->useOn($this);
$this->getLevel()->setBlock($this, Block::get(Item::FARMLAND, 0), true, false, true);
$this->getLevel()->setBlock($this, Block::get(Item::FARMLAND, 0), true);
return true;
}

View File

@ -23,6 +23,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\network\protocol\LevelEventPacket;
use pocketmine\Player;
use pocketmine\Server;
@ -34,6 +35,169 @@ abstract class Door extends Transparent{
$this->isSolid = false;
}
private function getFullDamage(){
$damage = $this->getDamage();
$flag = ($damage & 0x08) > 0;
if($flag){
$first = $this->getSide(0)->getDamage();
$second = $damage;
}else{
$first = $damage;
$second = $this->getSide(1)->getDamage();
}
$flag1 = ($second & 0x01) > 0;
return $first & 0x07 | ($flag ? 8 : 0) | ($flag1 ? 0x10 : 0);
}
public function getBoundingBox(){
$f = 0.1875;
$damage = $this->getFullDamage();
$bb = new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + 1,
$this->y + 2,
$this->z + 1
);
$j = $damage & 0x03;
$flag = (($damage & 0x04) > 0);
$flag1 = (($damage & 0x10) > 0);
if($j === 0){
if($flag){
if(!$flag1){
$bb = new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + 1,
$this->y + 1,
$this->z + $f
);
}else{
$bb = new AxisAlignedBB(
$this->x,
$this->y,
$this->z + 1 - $f,
$this->x + 1,
$this->y + 1,
$this->z + 1
);
}
}else{
$bb = new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + $f,
$this->y + 1,
$this->z + 1
);
}
}elseif($j === 1){
if($flag){
if(!$flag1){
$bb = new AxisAlignedBB(
$this->x + 1 - $f,
$this->y,
$this->z,
$this->x + 1,
$this->y + 1,
$this->z + 1
);
}else{
$bb = new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + $f,
$this->y + 1,
$this->z + 1
);
}
}else{
$bb = new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + 1,
$this->y + 1,
$this->z + $f
);
}
}elseif($j === 2){
if($flag){
if(!$flag1){
$bb = new AxisAlignedBB(
$this->x,
$this->y,
$this->z + 1 - $f,
$this->x + 1,
$this->y + 1,
$this->z + 1
);
}else{
$bb = new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + 1,
$this->y + 1,
$this->z + $f
);
}
}else{
$bb = new AxisAlignedBB(
$this->x + 1 - $f,
$this->y,
$this->z,
$this->x + 1,
$this->y + 1,
$this->z + 1
);
}
}elseif($j === 3){
if($flag){
if(!$flag1){
$bb = new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + $f,
$this->y + 1,
$this->z + 1
);
}else{
$bb = new AxisAlignedBB(
$this->x + 1 - $f,
$this->y,
$this->z,
$this->x + 1,
$this->y + 1,
$this->z + 1
);
}
}else{
$bb = new AxisAlignedBB(
$this->x,
$this->y,
$this->z + 1 - $f,
$this->x + 1,
$this->y + 1,
$this->z + 1
);
}
}
return $bb;
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->getID() === self::AIR){ //Replace with common break method
@ -57,22 +221,22 @@ abstract class Door extends Transparent{
return false;
}
$direction = $player instanceof Player ? $player->getDirection() : 0;
$face = array(
$face = [
0 => 3,
1 => 4,
2 => 2,
3 => 5,
);
];
$next = $this->getSide($face[(($direction + 2) % 4)]);
$next2 = $this->getSide($face[$direction]);
$metaUp = 0x08;
if($next->getID() === $this->id or ($next2->isTransparent === false and $next->isTransparent === true)){ //Door hinge
$metaUp |= 0x01;
}
$this->getLevel()->setBlock($blockUp, Block::get($this->id, $metaUp), true, false, true); //Top
$this->meta = $player->getDirection() & 0x03;
$this->getLevel()->setBlock($block, $this, true, false, true); //Bottom
$this->getLevel()->setBlock($block, $this, true, true); //Bottom
$this->getLevel()->setBlock($blockUp, $b = Block::get($this->id, $metaUp), true); //Top
return true;
}
@ -83,15 +247,15 @@ abstract class Door extends Transparent{
if(($this->meta & 0x08) === 0x08){
$down = $this->getSide(0);
if($down->getID() === $this->id){
$this->getLevel()->setBlock($down, new Air(), true, false, true);
$this->getLevel()->setBlock($down, new Air(), true);
}
}else{
$up = $this->getSide(1);
if($up->getID() === $this->id){
$this->getLevel()->setBlock($up, new Air(), true, false, true);
$this->getLevel()->setBlock($up, new Air(), true);
}
}
$this->getLevel()->setBlock($this, new Air(), true, false, true);
$this->getLevel()->setBlock($this, new Air(), true);
return true;
}
@ -101,7 +265,7 @@ abstract class Door extends Transparent{
$down = $this->getSide(0);
if($down->getID() === $this->id){
$meta = $down->getDamage() ^ 0x04;
$this->getLevel()->setBlock($down, Block::get($this->id, $meta), true, false, true);
$this->getLevel()->setBlock($down, Block::get($this->id, $meta), true);
$players = $this->getLevel()->getUsingChunk($this->x >> 4, $this->z >> 4);
if($player instanceof Player){
unset($players[$player->getID()]);
@ -120,7 +284,7 @@ abstract class Door extends Transparent{
return false;
}else{
$this->meta ^= 0x04;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
$players = $this->getLevel()->getUsingChunk($this->x >> 4, $this->z >> 4);
if($player instanceof Player){
unset($players[$player->getID()]);

View File

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

View File

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

View File

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

View File

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

View File

@ -21,9 +21,22 @@
namespace pocketmine\block;
use pocketmine\math\AxisAlignedBB;
class EndPortal extends Solid{
public function __construct($meta = 0){
parent::__construct(self::END_PORTAL, $meta, "End Portal");
$this->hardness = 18000000;
}
public function getBoundingBox(){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + 1,
$this->y + (($this->getDamage() & 0x04) > 0 ? 1 : 0.8125),
$this->z + 1
);
}
}

View File

@ -23,14 +23,51 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\Player;
use pocketmine\level\Level;
use pocketmine\entity\FallingBlock;
use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\Enum;
use pocketmine\nbt\tag\Double;
use pocketmine\nbt\tag\Float;
use pocketmine\nbt\tag\Byte;
class Fallable extends Solid{
abstract class Fallable extends Solid{
public $hasPhysics = true;
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$ret = $this->getLevel()->setBlock($this, $this, true, false, true);
$ret = $this->getLevel()->setBlock($this, $this, true, true);
return $ret;
}
public function onUpdate($type){
if($this->hasPhysics === true and $type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(0);
if($down->getID() === self::AIR or ($down instanceof Liquid)){
$fall = new FallingBlock($this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new Compound("", [
"Pos" => new Enum("Pos", [
new Double("", $this->x + 0.5),
new Double("", $this->y + 0.5),
new Double("", $this->z + 0.5)
]),
//TODO: add random motion with physics
"Motion" => new Enum("Motion", [
new Double("", 0),
new Double("", 0),
new Double("", 0)
]),
"Rotation" => new Enum("Rotation", [
new Float("", 0),
new Float("", 0)
]),
"Tile" => new Byte("Tile", $this->getID())
]));
$fall->spawnToAll();
}
return false;
}
}
}

View File

@ -22,6 +22,7 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
class Farmland extends Solid{
public function __construct($meta = 0){
@ -29,9 +30,20 @@ class Farmland extends Solid{
$this->hardness = 3;
}
public function getDrops(Item $item){
return array(
array(Item::DIRT, 0, 1),
public function getBoundingBox(){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + 1,
$this->y + 0.9375,
$this->z + 1
);
}
public function getDrops(Item $item){
return [
[Item::DIRT, 0, 1],
];
}
}

View File

@ -22,6 +22,9 @@
namespace pocketmine\block;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
class Fence extends Transparent{
public function __construct(){
parent::__construct(self::FENCE, 0, "Fence");
@ -29,4 +32,29 @@ class Fence extends Transparent{
$this->hardness = 15;
}
public function getBoundingBox(){
$flag = $this->canConnect($this->getSide(2));
$flag1 = $this->canConnect($this->getSide(3));
$flag2 = $this->canConnect($this->getSide(4));
$flag3 = $this->canConnect($this->getSide(5));
$f = $flag2 ? 0 : 0.375;
$f1 = $flag3 ? 1 : 0.625;
$f2 = $flag ? 0 : 0.375;
$f3 = $flag1 ? 1 : 0.625;
return new AxisAlignedBB(
$this->x + $f,
$this->y,
$this->z + $f2,
$this->x + $f1,
$this->y + 1, //TODO: check this, add extra bounding box
$this->z + $f3
);
}
public function canConnect(Block $block){
return ($block->getID() !== self::FENCE and $block->getID() !== self::FENCE_GATE) ? $block->isSolid : true;
}
}

View File

@ -22,6 +22,7 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\Player;
class FenceGate extends Transparent{
@ -36,39 +37,67 @@ class FenceGate extends Transparent{
$this->hardness = 15;
}
public function getBoundingBox(){
if(($this->getDamage() & 0x04) > 0){
return null;
}
$i = ($this->getDamage() & 0x03);
if($i === 2 and $i === 0){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z + 0.375,
$this->x + 1,
$this->y + 1,
$this->z + 0.625
);
}else{
return new AxisAlignedBB(
$this->x + 0.375,
$this->y,
$this->z,
$this->x + 0.625,
$this->y + 1,
$this->z + 1
);
}
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$faces = array(
$faces = [
0 => 3,
1 => 0,
2 => 1,
3 => 2,
);
];
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0] & 0x03;
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
public function onActivate(Item $item, Player $player = null){
$faces = array(
$faces = [
0 => 3,
1 => 0,
2 => 1,
3 => 2,
);
];
$this->meta = ($faces[$player instanceof Player ? $player->getDirection() : 0] & 0x03) | ((~$this->meta) & 0x04);
if(($this->meta & 0x04) === 0x04){
$this->isFullBlock = true;
}else{
$this->isFullBlock = false;
}
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
return true;
}

View File

@ -22,7 +22,10 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\entity\Entity;
use pocketmine\level\Level;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\Server;
class Fire extends Flowable{
public function __construct($meta = 0){
@ -37,6 +40,14 @@ class Fire extends Flowable{
return null;
}
public function onEntityCollide(Entity $entity){
$entity->setOnFire(8);
$ev = new EntityDamageEvent($entity, EntityDamageEvent::CAUSE_FIRE, 1);
Server::getInstance()->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$entity->attack($ev->getFinalDamage(), $ev);
}
}
public function getDrops(Item $item){
return [];
@ -50,12 +61,12 @@ class Fire extends Flowable{
return false;
}
}
$this->getLevel()->setBlock($this, new Air(), true, false, true);
$this->getLevel()->setBlock($this, new Air(), true);
return Level::BLOCK_UPDATE_NORMAL;
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if($this->getSide(0)->getID() !== self::NETHERRACK){
$this->getLevel()->setBlock($this, new Air(), true, false, true);
$this->getLevel()->setBlock($this, new Air(), true);
return Level::BLOCK_UPDATE_NORMAL;
}

View File

@ -22,7 +22,7 @@
namespace pocketmine\block;
class Flowable extends Transparent{
abstract class Flowable extends Transparent{
public $isFlowable = true;
public $isFullBlock = false;

View File

@ -28,7 +28,7 @@ use pocketmine\Player;
class Generic extends Block{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
return $this->getLevel()->setBlock($this, $this, true, false, true);
return $this->getLevel()->setBlock($this, $this, true, true);
}
public function isBreakable(Item $item){
@ -36,29 +36,10 @@ class Generic extends Block{
}
public function onBreak(Item $item){
return $this->getLevel()->setBlock($this, new Air(), true, false, true);
return $this->getLevel()->setBlock($this, new Air(), true, true);
}
public function onUpdate($type){
if($this->hasPhysics === true and $type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(0);
if($down->getID() === self::AIR or ($down instanceof Liquid)){
$data = array(
"x" => $this->x + 0.5,
"y" => $this->y + 0.5,
"z" => $this->z + 0.5,
"Tile" => $this->id,
);
/*$this->getLevel()->setBlock($this, new Air(), false, false, true);
//TODO
//$e = $server->api->entity->add($this->getLevel(), ENTITY_FALLING, FALLING_SAND, $data);
//$e->spawnToAll();
$server->api->block->blockUpdateAround(clone $this, Level::BLOCK_UPDATE_NORMAL, 1);*/
}
return false;
}
return false;
}

View File

@ -22,11 +22,9 @@
namespace pocketmine\block;
class GlassPane extends Transparent{
class GlassPane extends Thin{
public function __construct(){
parent::__construct(self::GLASS_PANE, 0, "Glass Pane");
$this->isFullBlock = false;
$this->isSolid = false;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -22,7 +22,7 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\generator\object\TallGrass;
use pocketmine\level\generator\object\TallGrass as TallGrassObject;
use pocketmine\level\Level;
use pocketmine\level\Position;
use pocketmine\Player;
@ -65,7 +65,7 @@ class Grass extends Solid{
public function onActivate(Item $item, Player $player = null){
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){
$item->count--;
TallGrass::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2);
TallGrassObject::growGrass($this->getLevel(), $this, new Random(mt_rand()), 8, 2);
return true;
}elseif($item->isHoe()){

View File

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

View File

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

View File

@ -30,7 +30,7 @@ class Ice extends Transparent{
}
public function onBreak(Item $item){
$this->getLevel()->setBlock($this, new Water(), true, false, true);
$this->getLevel()->setBlock($this, new Water(), true);
return true;
}

View File

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

View File

@ -22,11 +22,9 @@
namespace pocketmine\block;
class IronBars extends Transparent{
class IronBars extends Thin{
public function __construct(){
parent::__construct(self::IRON_BARS, 0, "Iron Bars");
$this->isFullBlock = false;
$this->isSolid = false;
}
}

View File

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

View File

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

View File

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

View File

@ -23,7 +23,9 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\Player;
use pocketmine\entity\Entity;
class Ladder extends Transparent{
public function __construct($meta = 0){
@ -33,22 +35,66 @@ class Ladder extends Transparent{
$this->hardness = 2;
}
public function onEntityCollide(Entity $entity){
$entity->fallDistance = 0;
}
public function getBoundingBox(){
$f = 0.125;
if($this->meta === 2){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z + 1 - $f,
$this->x + 1,
$this->y + 1,
$this->z + 1
);
}elseif($this->meta === 3){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + 1,
$this->y + 1,
$this->z + $f
);
}elseif($this->meta === 4){
return new AxisAlignedBB(
$this->x + 1 - $f,
$this->y,
$this->z,
$this->x + 1,
$this->y + 1,
$this->z + 1
);
}elseif($this->meta === 5){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + $f,
$this->y + 1,
$this->z + 1
);
}
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
if($target->isTransparent === false){
$faces = array(
$faces = [
2 => 2,
3 => 3,
4 => 4,
5 => 5,
);
];
if(isset($faces[$face])){
$this->meta = $faces[$face];
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -70,8 +116,8 @@ class Ladder extends Transparent{
}
public function getDrops(Item $item){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}
}

View File

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

View File

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

View File

@ -22,10 +22,12 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\entity\Entity;
use pocketmine\level\Level;
use pocketmine\level\Position;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\event\entity\EntityDamageEvent;
class Lava extends Liquid{
public function __construct($meta = 0){
@ -37,123 +39,21 @@ class Lava extends Liquid{
return null;
}
public function onEntityCollide(Entity $entity){
$entity->fallDistance *= 0.5;
$entity->setOnFire(15);
$ev = new EntityDamageEvent($entity, EntityDamageEvent::CAUSE_LAVA, 4);
Server::getInstance()->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$entity->attack($ev->getFinalDamage(), $ev);
}
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$ret = $this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->scheduleUpdate(clone $this, 40);
$ret = $this->getLevel()->setBlock($this, $this, true, false);
$this->getLevel()->scheduleUpdate($this, $this->tickRate());
return $ret;
}
public function getSourceCount(){
$count = 0;
for($side = 2; $side <= 5; ++$side){
if($this->getSide($side) instanceof Lava){
$b = $this->getSide($side);
$level = $b->meta & 0x07;
if($level == 0x00){
$count++;
}
}
}
return $count;
}
public function checkWater(){
for($side = 1; $side <= 5; ++$side){
$b = $this->getSide($side);
if($b instanceof Water){
$level = $this->meta & 0x07;
if($level == 0x00){
$this->getLevel()->setBlock($this, new Obsidian(), false, false, true);
}else{
$this->getLevel()->setBlock($this, new Cobblestone(), false, false, true);
}
}
}
}
public function getFrom(){
for($side = 0; $side <= 5; ++$side){
$b = $this->getSide($side);
if($b instanceof Lava){
$tlevel = $b->meta & 0x07;
$level = $this->meta & 0x07;
if(($tlevel + 2) == $level || ($side == 0x01 && $level == 0x01) || ($tlevel == 6 && $level == 7)){
return $b;
}
}
}
return null;
}
public function onUpdate($type){
return false;
$newId = $this->id;
$level = $this->meta & 0x07;
if($type !== Level::BLOCK_UPDATE_NORMAL){
return false;
}
if($this->checkWater()){
return;
}
$falling = $this->meta >> 3;
$down = $this->getSide(0);
$from = $this->getFrom();
if($from !== null || $level == 0x00){
if($level !== 0x07){
if($down instanceof Air || $down instanceof Lava){
$this->getLevel()->setBlock($down, new Lava(0x01), false, false, true);
Server::getInstance()->api->block->scheduleBlockUpdate(new Position($down, 0, 0, $this->level), 40, Level::BLOCK_UPDATE_NORMAL);
}else{
for($side = 2; $side <= 5; ++$side){
$b = $this->getSide($side);
if($b instanceof Lava){
}elseif($b->isFlowable === true){
$this->getLevel()->setBlock($b, new Lava(min($level + 2, 7)), false, false, true);
Server::getInstance()->api->block->scheduleBlockUpdate(Position::fromObject($b, $this->level), 40, Level::BLOCK_UPDATE_NORMAL);
}
}
}
}
}else{
//Extend Remove for Left Lavas
for($side = 2; $side <= 5; ++$side){
$sb = $this->getSide($side);
if($sb instanceof Lava){
$tlevel = $sb->meta & 0x07;
if($tlevel != 0x00){
for($s = 0; $s <= 5; $s++){
$ssb = $sb->getSide($s);
Server::getInstance()->api->block->scheduleBlockUpdate(Position::fromObject($ssb, $this->level), 40, Level::BLOCK_UPDATE_NORMAL);
}
$this->getLevel()->setBlock($sb, new Air(), false, false, true);
}
}
$b = $this->getSide(0)->getSide($side);
if($b instanceof Lava){
$tlevel = $b->meta & 0x07;
if($tlevel != 0x00){
for($s = 0; $s <= 5; $s++){
$ssb = $sb->getSide($s);
Server::getInstance()->api->block->scheduleBlockUpdate(Position::fromObject($ssb, $this->level), 40, Level::BLOCK_UPDATE_NORMAL);
}
$this->getLevel()->setBlock($b, new Air(), false, false, true);
}
}
//Server::getInstance()->api->block->scheduleBlockUpdate(Position::fromObject($b, $this->level), 10, Level::BLOCK_UPDATE_NORMAL);
}
$this->getLevel()->setBlock($this, new Air(), false, false, true);
}
return false;
}
}

View File

@ -35,12 +35,12 @@ class Leaves extends Transparent{
public function __construct($meta = 0){
parent::__construct(self::LEAVES, $meta, "Leaves");
$names = array(
$names = [
self::OAK => "Oak Leaves",
self::SPRUCE => "Spruce Leaves",
self::BIRCH => "Birch Leaves",
self::JUNGLE => "Jungle Leaves",
);
];
$this->name = $names[$this->meta & 0x03];
$this->hardness = 1;
}
@ -142,19 +142,19 @@ class Leaves extends Transparent{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$this->meta |= 0x04;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
}
public function getDrops(Item $item){
$drops = [];
if($item->isShears()){
$drops[] = array(Item::LEAVES, $this->meta & 0x03, 1);
$drops[] = [Item::LEAVES, $this->meta & 0x03, 1];
}else{
if(mt_rand(1, 20) === 1){ //Saplings
$drops[] = array(Item::SAPLING, $this->meta & 0x03, 1);
$drops[] = [Item::SAPLING, $this->meta & 0x03, 1];
}
if(($this->meta & 0x03) === self::OAK and mt_rand(1, 200) === 1){ //Apples
$drops[] = array(Item::APPLE, 0, 1);
$drops[] = [Item::APPLE, 0, 1];
}
}

View File

@ -29,10 +29,10 @@ class Leaves2 extends Leaves{
public function __construct($meta = 0){
Transparent::__construct(self::LEAVES, $meta, "Leaves");
$names = array(
$names = [
self::ACACIA => "Acacia Leaves",
self::DARK_OAK => "Dark Oak Leaves",
);
];
$this->name = $names[$this->meta & 0x03];
$this->hardness = 1;
}
@ -131,16 +131,16 @@ class Leaves2 extends Leaves{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$this->meta |= 0x04;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
}
public function getDrops(Item $item){
$drops = [];
if($item->isShears()){
$drops[] = array(Item::LEAVES2, $this->meta & 0x03, 1);
$drops[] = [Item::LEAVES2, $this->meta & 0x03, 1];
}else{
if(mt_rand(1, 20) === 1){ //Saplings
$drops[] = array(Item::SAPLING, $this->meta & 0x03, 1);
$drops[] = [Item::SAPLING, $this->meta & 0x03, 1];
}
}

View File

@ -22,10 +22,390 @@
namespace pocketmine\block;
class Liquid extends Transparent{
use pocketmine\entity\Entity;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
abstract class Liquid extends Transparent{
public $isLiquid = true;
public $breakable = false;
public $isReplaceable = true;
public $isSolid = false;
public $isFullBlock = true;
public $adjacentSources = 0;
public $isOptimalFlowDirection = [0, 0, 0];
public $flowCost = [0, 0, 0];
public function getFluidHeightPercent(){
$d = $this->meta;
if($d >= 8){
$d = 0;
}
return ($d + 1) / 9;
}
protected function getFlowDecay(Vector3 $pos){
if(!($pos instanceof Block)){
$pos = $this->getLevel()->getBlock($pos);
}
if($pos->getID() !== $this->getID()){
return -1;
}else{
return $pos->getDamage();
}
}
protected function getEffectiveFlowDecay(Vector3 $pos){
if(!($pos instanceof Block)){
$pos = $this->getLevel()->getBlock($pos);
}
if($pos->getID() !== $this->getID()){
return -1;
}
$decay = $pos->getDamage();
if($decay >= 8){
$decay = 0;
}
return $decay;
}
public function getFlowVector(){
$vector = new Vector3(0, 0, 0);
$decay = $this->getEffectiveFlowDecay($this);
for($j = 0; $j < 4; ++$j){
$x = $this->x;
$y = $this->y;
$z = $this->z;
if($j === 0){
--$x;
}elseif($j === 1){
++$x;
}elseif($j === 2){
--$z;
}elseif($j === 3){
++$z;
}
$sideBlock = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
$blockDecay = $this->getEffectiveFlowDecay($sideBlock);
if($blockDecay < 0){
if(!$sideBlock->isFlowable){
continue;
}
$blockDecay = $this->getEffectiveFlowDecay($sideBlock->getSide(0));
if($blockDecay >= 0){
$realDecay = $blockDecay - ($decay - 8);
$vector = $vector->add(($sideBlock->x - $this->x) * $realDecay, ($sideBlock->y - $this->y) * $realDecay, ($sideBlock->z - $this->z) * $realDecay);
}
continue;
}else{
$realDecay = $blockDecay - $decay;
$vector = $vector->add(($sideBlock->x - $this->x) * $realDecay, ($sideBlock->y - $this->y) * $realDecay, ($sideBlock->z - $this->z) * $realDecay);
}
}
if($this->getDamage() >= 8){
$falling = false;
if(!$this->getLevel()->getBlock($this->add(0, 0, -1))->isFlowable){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(0, 0, 1))->isFlowable){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(-1, 0, 0))->isFlowable){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(1, 0, 0))->isFlowable){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(0, 1, -1))->isFlowable){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(0, 1, 1))->isFlowable){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(-1, 1, 0))->isFlowable){
$falling = true;
}elseif(!$this->getLevel()->getBlock($this->add(1, 1, 0))->isFlowable){
$falling = true;
}
if($falling){
$vector = $vector->normalize()->add(0, -6, 0);
}
}
return $vector->normalize();
}
public function addVelocityToEntity(Entity $entity, Vector3 $vector){
$flow = $this->getFlowVector();
$vector->x += $flow->x;
$vector->y += $flow->y;
$vector->z += $flow->z;
}
public function tickRate(){
if($this instanceof Water){
return 5;
}elseif($this instanceof Lava){
return 30;
}
return 0;
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$this->checkForHarden();
$this->getLevel()->scheduleUpdate($this, $this->tickRate());
}elseif($type === Level::BLOCK_UPDATE_SCHEDULED){
$decay = $this->getFlowDecay($this);
$multiplier = $this instanceof Lava ? 2 : 1;
$flag = true;
if($decay > 0){
$smallestFlowDecay = -100;
$this->adjacentSources = 0;
$smallestFlowDecay = $this->getSmallestFlowDecay($this->getSide(4), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->getSide(5), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->getSide(2), $smallestFlowDecay);
$smallestFlowDecay = $this->getSmallestFlowDecay($this->getSide(3), $smallestFlowDecay);
$k = $smallestFlowDecay + $multiplier;
if($k >= 8 or $smallestFlowDecay < 0){
$k = -1;
}
if(($topFlowDecay = $this->getFlowDecay($this->getSide(1))) >= 0){
if($topFlowDecay >= 8){
$k = $topFlowDecay;
}else{
$k = $topFlowDecay | 0x08;
}
}
if($this->adjacentSources >= 2 and $this instanceof Water){
$bottomBlock = $this->getSide(0);
if($bottomBlock->isSolid){
$k = 0;
}elseif($bottomBlock instanceof Water and $bottomBlock->getDamage() === 0){
$k = 0;
}
}
if($this instanceof Lava and $decay < 8 and $k < 8 and $k > 1 and mt_rand(0, 4) !== 0){
$k = $decay;
$flag = false;
}
if($k !== $decay){
$decay = $k;
if($decay < 0){
$this->getLevel()->setBlock($this, Block::get(Item::AIR), true);
}else{
$this->getLevel()->setBlock($this, Block::get($this->id, $decay), true);
$this->getLevel()->scheduleUpdate($this, $this->tickRate());
}
}elseif($flag){
$this->getLevel()->scheduleUpdate($this, $this->tickRate());
//$this->updateFlow();
}
}else{
//$this->updateFlow();
}
$bottomBlock = $this->getSide(0);
if($bottomBlock->isFlowable or $bottomBlock instanceof Liquid){
if($this instanceof Lava and $bottomBlock instanceof Water){
$this->getLevel()->setBlock($bottomBlock, Block::get(Item::STONE), true);
return;
}
if($decay >= 8){
$this->getLevel()->setBlock($bottomBlock, Block::get($this->id, $decay), true);
$this->getLevel()->scheduleUpdate($bottomBlock, $this->tickRate());
}else{
$this->getLevel()->setBlock($bottomBlock, Block::get($this->id, $decay + 8), true);
$this->getLevel()->scheduleUpdate($bottomBlock, $this->tickRate());
}
}elseif($decay >= 0 and ($decay === 0 or !$bottomBlock->isFlowable)){
$flags = $this->getOptimalFlowDirections();
$l = $decay + $multiplier;
if($decay >= 8){
$l = 1;
}
if($l >= 8){
$this->checkForHarden();
return;
}
if($flags[0]){
$this->flowIntoBlock($this->getSide(4), $l);
}
if($flags[1]){
$this->flowIntoBlock($this->getSide(5), $l);
}
if($flags[2]){
$this->flowIntoBlock($this->getSide(2), $l);
}
if($flags[3]){
$this->flowIntoBlock($this->getSide(3), $l);
}
}
$this->checkForHarden();
}
}
private function flowIntoBlock(Block $block, $newFlowDecay){
if($block->isFlowable){
if($block->getID() > 0){
$this->getLevel()->useBreakOn($block);
}
$this->getLevel()->setBlock($block, Block::get($this->id, $newFlowDecay), true);
$this->getLevel()->scheduleUpdate($block, $this->tickRate());
}
}
private function calculateFlowCost(Block $block, $accumulatedCost, $previousDirection){
$cost = 1000;
for($j = 0; $j < 4; ++$j){
if(
($j === 0 and $previousDirection === 1) or
($j === 1 and $previousDirection === 0) or
($j === 2 and $previousDirection === 3) or
($j === 3 and $previousDirection === 2)
){
$x = $block->x;
$y = $block->y;
$z = $block->z;
if($j === 0){
--$x;
}elseif($j === 1){
++$x;
}elseif($j === 2){
--$z;
}elseif($j === 3){
++$z;
}
$blockSide = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
if(!$blockSide->isFlowable or ($blockSide instanceof Liquid and $blockSide->getDamage() === 0)){
continue;
}elseif($blockSide->getSide(0)->isFlowable){
return $accumulatedCost;
}
if($accumulatedCost >= 4){
continue;
}
$realCost = $this->calculateFlowCost($blockSide, $accumulatedCost + 1, $j);
if($realCost < $cost){
$cost = $realCost;
}
}
}
return $cost;
}
private function getOptimalFlowDirections(){
for($j = 0; $j < 4; ++$j){
$this->flowCost[$j] = 1000;
$x = $this->x;
$y = $this->y;
$z = $this->z;
if($j === 0){
--$x;
}elseif($j === 1){
++$x;
}elseif($j === 2){
--$z;
}elseif($j === 3){
++$z;
}
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
if(!$block->isFlowable or ($block instanceof Liquid and $block->getDamage() === 0)){
continue;
}elseif($block->getSide(0)->isFlowable){
$this->flowCost[$j] = 0;
}else{
$this->flowCost[$j] = $this->calculateFlowCost($block, 1, $j);
}
}
$minCost = $this->flowCost[0];
for($i = 1; $i < 4; ++$i){
if($this->flowCost[$i] < $minCost){
$minCost = $this->flowCost[$i];
}
}
for($i = 0; $i < 4; ++$i){
$this->isOptimalFlowDirection[$i] = ($this->flowCost[$i] === $minCost);
}
return $this->isOptimalFlowDirection;
}
private function getSmallestFlowDecay(Vector3 $pos, $decay){
$blockDecay = $this->getFlowDecay($pos);
if($blockDecay < 0){
return $decay;
}elseif($blockDecay === 0){
++$this->adjacentSources;
}elseif($blockDecay >= 8){
$blockDecay = 0;
}
return ($decay >= 0 && $blockDecay >= $decay) ? $decay : $blockDecay;
}
private function checkForHarden(){
if($this instanceof Lava){
$colliding = false;
for($side = 0; $side <= 5 and !$colliding; ++$side){
$colliding = $this->getSide($side) instanceof Water;
}
if($colliding){
if($this->getDamage() === 0){
$this->getLevel()->setBlock($this, Block::get(Item::OBSIDIAN), true);
}elseif($this->getDamage() <= 4){
$this->getLevel()->setBlock($this, Block::get(Item::COBBLESTONE), true);
}
}
}
}
}

View File

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

View File

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

View File

@ -40,7 +40,7 @@ class MelonStem extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -60,7 +60,7 @@ class MelonStem extends Flowable{
if(mt_rand(0, 2) == 1){
if($this->meta < 0x07){
++$this->meta;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
return Level::BLOCK_UPDATE_RANDOM;
}else{
@ -73,7 +73,7 @@ class MelonStem extends Flowable{
$side = $this->getSide(mt_rand(2, 5));
$d = $side->getSide(0);
if($side->getID() === self::AIR and ($d->getID() === self::FARMLAND or $d->getID() === self::GRASS or $d->getID() === self::DIRT)){
$this->getLevel()->setBlock($side, new Melon(), true, false, true);
$this->getLevel()->setBlock($side, new Melon(), true);
}
}
}
@ -87,7 +87,7 @@ class MelonStem extends Flowable{
public function onActivate(Item $item, Player $player = null){
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
$this->meta = 0x07;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
if(($player->gamemode & 0x01) === 0){
$item->count--;
}
@ -99,8 +99,8 @@ class MelonStem extends Flowable{
}
public function getDrops(Item $item){
return array(
array(Item::MELON_SEEDS, 0, mt_rand(0, 2)),
);
return [
[Item::MELON_SEEDS, 0, mt_rand(0, 2)],
];
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -40,7 +40,7 @@ class Potato extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -50,8 +50,11 @@ class Potato extends Flowable{
public function onActivate(Item $item, Player $player = null){
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
$this->meta = 0x07;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->meta += mt_rand(2, 5);
if($this->meta > 7){
$this->meta = 7;
}
$this->getLevel()->setBlock($this, $this, true);
if(($player->gamemode & 0x01) === 0){
$item->count--;
}
@ -74,7 +77,7 @@ class Potato extends Flowable{
if(mt_rand(0, 2) == 1){
if($this->meta < 0x07){
++$this->meta;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
return Level::BLOCK_UPDATE_RANDOM;
}
@ -89,9 +92,9 @@ class Potato extends Flowable{
public function getDrops(Item $item){
$drops = [];
if($this->meta >= 0x07){
$drops[] = array(Item::POTATO, 0, mt_rand(1, 4));
$drops[] = [Item::POTATO, 0, mt_rand(1, 4)];
}else{
$drops[] = array(Item::POTATO, 0, 1);
$drops[] = [Item::POTATO, 0, 1];
}
return $drops;

View File

@ -21,6 +21,8 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\Player;
class Pumpkin extends Solid{
public function __construct(){
@ -28,4 +30,13 @@ class Pumpkin extends Solid{
$this->hardness = 5;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
if($player instanceof Player){
$this->meta = ((int) $player->getDirection() + 5) % 4;
}
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
}

View File

@ -40,7 +40,7 @@ class PumpkinStem extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -61,7 +61,7 @@ class PumpkinStem extends Flowable{
if(mt_rand(0, 2) == 1){
if($this->meta < 0x07){
++$this->meta;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
return Level::BLOCK_UPDATE_RANDOM;
}else{
@ -74,7 +74,7 @@ class PumpkinStem extends Flowable{
$side = $this->getSide(mt_rand(2, 5));
$d = $side->getSide(0);
if($side->getID() === self::AIR and ($d->getID() === self::FARMLAND or $d->getID() === self::GRASS or $d->getID() === self::DIRT)){
$this->getLevel()->setBlock($side, new Pumpkin(), true, false, true);
$this->getLevel()->setBlock($side, new Pumpkin(), true);
}
}
}
@ -88,7 +88,7 @@ class PumpkinStem extends Flowable{
public function onActivate(Item $item, Player $player = null){
if($item->getID() === Item::DYE and $item->getDamage() === 0x0F){ //Bonemeal
$this->meta = 0x07;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
if(($player->gamemode & 0x01) === 0){
$item->count--;
}
@ -100,8 +100,8 @@ class PumpkinStem extends Flowable{
}
public function getDrops(Item $item){
return array(
array(Item::PUMPKIN_SEEDS, 0, mt_rand(0, 2)),
);
return [
[Item::PUMPKIN_SEEDS, 0, mt_rand(0, 2)],
];
}
}

View File

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

View File

@ -53,7 +53,7 @@ class RedMushroom extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->isTransparent === false){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}

View File

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

View File

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

View File

@ -37,14 +37,14 @@ class Sapling extends Flowable{
public function __construct($meta = Sapling::OAK){
parent::__construct(self::SAPLING, $meta, "Sapling");
$this->isActivable = true;
$names = array(
$names = [
0 => "Oak Sapling",
1 => "Spruce Sapling",
2 => "Birch Sapling",
3 => "Jungle Sapling",
4 => "Acacia Sapling",
5 => "Dark Oak Sapling",
);
];
$this->name = $names[$this->meta & 0x07];
$this->hardness = 0;
}
@ -57,7 +57,7 @@ class Sapling extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::GRASS or $down->getID() === self::DIRT or $down->getID() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -94,7 +94,7 @@ class Sapling extends Flowable{
Tree::growTree($this->getLevel(), $this->x, $this->y, $this->z, new Random(mt_rand()), $this->meta & 0x07);
}else{
$this->meta |= 0x08;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
return Level::BLOCK_UPDATE_RANDOM;
}
@ -107,8 +107,8 @@ class Sapling extends Flowable{
}
public function getDrops(Item $item){
return array(
array($this->id, $this->meta & 0x07, 1),
);
return [
[$this->id, $this->meta & 0x07, 1],
];
}
}

View File

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

View File

@ -22,12 +22,13 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\Player;
class Slab extends Transparent{
public function __construct($meta = 0){
parent::__construct(self::SLAB, $meta, "Slab");
$names = array(
$names = [
0 => "Stone",
1 => "Sandstone",
2 => "Wooden",
@ -36,7 +37,7 @@ class Slab extends Transparent{
5 => "Stone Brick",
6 => "Quartz",
7 => "",
);
];
$this->name = (($this->meta & 0x08) === 0x08 ? "Upper " : "") . $names[$this->meta & 0x07] . " Slab";
if(($this->meta & 0x08) === 0x08){
$this->isFullBlock = true;
@ -46,15 +47,37 @@ class Slab extends Transparent{
$this->hardness = 30;
}
public function getBoundingBox(){
if(($this->meta & 0x08) > 0){
return new AxisAlignedBB(
$this->x,
$this->y + 0.5,
$this->z,
$this->x + 1,
$this->y + 1,
$this->z + 1
);
}else{
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + 1,
$this->y + 0.5,
$this->z + 1
);
}
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$this->meta &= 0x07;
if($face === 0){
if($target->getID() === self::SLAB and ($target->getDamage() & 0x08) === 0x08 and ($target->getDamage() & 0x07) === ($this->meta & 0x07)){
$this->getLevel()->setBlock($target, Block::get(Item::DOUBLE_SLAB, $this->meta), true, false, true);
$this->getLevel()->setBlock($target, Block::get(Item::DOUBLE_SLAB, $this->meta), true);
return true;
}elseif($block->getID() === self::SLAB and ($block->getDamage() & 0x07) === ($this->meta & 0x07)){
$this->getLevel()->setBlock($block, Block::get(Item::DOUBLE_SLAB, $this->meta), true, false, true);
$this->getLevel()->setBlock($block, Block::get(Item::DOUBLE_SLAB, $this->meta), true);
return true;
}else{
@ -62,19 +85,19 @@ class Slab extends Transparent{
}
}elseif($face === 1){
if($target->getID() === self::SLAB and ($target->getDamage() & 0x08) === 0 and ($target->getDamage() & 0x07) === ($this->meta & 0x07)){
$this->getLevel()->setBlock($target, Block::get(Item::DOUBLE_SLAB, $this->meta), true, false, true);
$this->getLevel()->setBlock($target, Block::get(Item::DOUBLE_SLAB, $this->meta), true);
return true;
}elseif($block->getID() === self::SLAB and ($block->getDamage() & 0x07) === ($this->meta & 0x07)){
$this->getLevel()->setBlock($block, Block::get(Item::DOUBLE_SLAB, $this->meta), true, false, true);
$this->getLevel()->setBlock($block, Block::get(Item::DOUBLE_SLAB, $this->meta), true);
return true;
}
//TODO: check for collision
}elseif(!($player instanceof Player)){
}else{
if($block->getID() === self::SLAB){
if(($block->getDamage() & 0x07) === ($this->meta & 0x07)){
$this->getLevel()->setBlock($block, Block::get(Item::DOUBLE_SLAB, $this->meta), true, false, true);
$this->getLevel()->setBlock($block, Block::get(Item::DOUBLE_SLAB, $this->meta), true);
return true;
}
@ -85,13 +108,12 @@ class Slab extends Transparent{
$this->meta |= 0x08;
}
}
}else{
return false;
}
if($block->getID() === self::SLAB and ($target->getDamage() & 0x07) !== ($this->meta & 0x07)){
return false;
}
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -116,9 +138,9 @@ class Slab extends Transparent{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array($this->id, $this->meta & 0x07, 1),
);
return [
[$this->id, $this->meta & 0x07, 1],
];
}else{
return [];
}

View File

@ -42,7 +42,7 @@ class SnowLayer extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down instanceof Solid){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true);
return true;
}
@ -53,7 +53,7 @@ class SnowLayer extends Flowable{
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->getID() === self::AIR){ //Replace with common break method
$this->getLevel()->setBlock($this, new Air(), true, false, true);
$this->getLevel()->setBlock($this, new Air(), true);
return Level::BLOCK_UPDATE_NORMAL;
}
@ -64,9 +64,9 @@ class SnowLayer extends Flowable{
public function getDrops(Item $item){
if($item->isShovel() !== false){
return array(
array(Item::SNOWBALL, 0, 1),
);
return [
[Item::SNOWBALL, 0, 1],
];
}
return [];

View File

@ -22,7 +22,7 @@
namespace pocketmine\block;
class Solid extends Generic{
abstract class Solid extends Generic{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);

View File

@ -22,10 +22,23 @@
namespace pocketmine\block;
use pocketmine\math\AxisAlignedBB;
class SoulSand extends Solid{
public function __construct(){
parent::__construct(self::SOUL_SAND, 0, "Soul Sand");
$this->hardness = 2.5;
}
public function getBoundingBox(){
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + 1,
$this->y + 1 - 0.125,
$this->z + 1
);
}
}

View File

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

View File

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

View File

@ -22,9 +22,10 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\Player;
class Stair extends Transparent{
abstract class Stair extends Transparent{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
@ -36,27 +37,125 @@ class Stair extends Transparent{
$this->hardness = 30;
}
/*
public function collidesWithBB(AxisAlignedBB $bb, &$list = []){
$damage = $this->getDamage();
$j = $damage & 0x03;
$f = 0;
$f1 = 0.5;
$f2 = 0.5;
$f3 = 1;
if(($damage & 0x04) > 0){
$f = 0.5;
$f1 = 1;
$f2 = 0;
$f3 = 0.5;
}
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
$this->x,
$this->y + $f,
$this->z,
$this->x + 1,
$this->y + $f1,
$this->z + 1
))){
$list[] = $bb2;
}
if($j === 0){
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
$this->x + 0.5,
$this->y + $f2,
$this->z,
$this->x + 1,
$this->y + $f3,
$this->z + 1
))){
$list[] = $bb2;
}
}elseif($j === 1){
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
$this->x,
$this->y + $f2,
$this->z,
$this->x + 0.5,
$this->y + $f3,
$this->z + 1
))){
$list[] = $bb2;
}
}elseif($j === 2){
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
$this->x,
$this->y + $f2,
$this->z + 0.5,
$this->x + 1,
$this->y + $f3,
$this->z + 1
))){
$list[] = $bb2;
}
}elseif($j === 3){
if($bb->intersectsWith($bb2 = new AxisAlignedBB(
$this->x,
$this->y + $f2,
$this->z,
$this->x + 1,
$this->y + $f3,
$this->z + 0.5
))){
$list[] = $bb2;
}
}
}
*/
public function getBoundingBox(){
if(($this->getDamage() & 0x04) > 0){
return new AxisAlignedBB(
$this->x,
$this->y + 0.5,
$this->z,
$this->x + 1,
$this->y + 1,
$this->z + 1
);
}else{
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z,
$this->x + 1,
$this->y + 0.5,
$this->z + 1
);
}
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$faces = array(
$faces = [
0 => 0,
1 => 2,
2 => 1,
3 => 3,
);
];
$this->meta = $faces[$player->getDirection()] & 0x03;
if(($fy > 0.5 and $face !== 1) or $face === 0){
$this->meta |= 0x04; //Upside-down stairs
}
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array($this->id, 0, 1),
);
return [
[$this->id, 0, 1],
];
}else{
return [];
}

View File

@ -21,11 +21,18 @@
namespace pocketmine\block;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\Server;
use pocketmine\entity\Entity;
class StillLava extends Liquid{
class StillLava extends Lava{
public function __construct($meta = 0){
parent::__construct(self::STILL_LAVA, $meta, "Still Lava");
$this->hardness = 500;
}
public function getBoundingBox(){
return null;
}
}

View File

@ -21,7 +21,6 @@
namespace pocketmine\block;
class StillWater extends Water{
public function __construct($meta = 0){
Liquid::__construct(self::STILL_WATER, $meta, "Still Water");

View File

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

View File

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

View File

@ -22,6 +22,8 @@
namespace pocketmine\block;
use pocketmine\math\AxisAlignedBB;
class StoneWall extends Transparent{
public function __construct($meta = 0){
$meta &= 0x01;
@ -34,4 +36,40 @@ class StoneWall extends Transparent{
$this->hardness = 30;
}
public function getBoundingBox(){
$flag = $this->canConnect($this->getSide(2));
$flag1 = $this->canConnect($this->getSide(3));
$flag2 = $this->canConnect($this->getSide(4));
$flag3 = $this->canConnect($this->getSide(5));
$f = $flag2 ? 0 : 0.25;
$f1 = $flag3 ? 1 : 0.75;
$f2 = $flag ? 0 : 0.25;
$f3 = $flag1 ? 1 : 0.75;
$f4 = 1;
if($flag and $flag1 and !$flag2 and !$flag3){
$f4 = 0.8125;
$f = 0.3125;
$f1 = 0.6875;
}elseif(!$flag and !$flag1 and $flag2 and $flag3){
$f4 = 0.8125;
$f2 = 0.3125;
$f3 = 0.6875;
}
return new AxisAlignedBB(
$this->x + $f,
$this->y,
$this->z + $f2,
$this->x + $f1,
$this->y + $f4,
$this->z + $f3
);
}
public function canConnect(Block $block){
return ($block->getID() !== self::COBBLE_WALL and $block->getID() !== self::FENCE_GATE) ? $block->isSolid : true;
}
}

View File

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

View File

@ -38,9 +38,9 @@ class Sugarcane extends Flowable{
public function getDrops(Item $item){
return array(
array(Item::SUGARCANE, 0, 1),
);
return [
[Item::SUGARCANE, 0, 1],
];
}
public function onActivate(Item $item, Player $player = null){
@ -49,12 +49,12 @@ class Sugarcane extends Flowable{
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlock(new Vector3($this->x, $this->y + $y, $this->z));
if($b->getID() === self::AIR){
$this->getLevel()->setBlock($b, new Sugarcane(), true, false, true);
$this->getLevel()->setBlock($b, new Sugarcane(), true);
break;
}
}
$this->meta = 0;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
}
if(($player->gamemode & 0x01) === 0){
$item->count--;
@ -82,15 +82,15 @@ class Sugarcane extends Flowable{
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlock(new Vector3($this->x, $this->y + $y, $this->z));
if($b->getID() === self::AIR){
$this->getLevel()->setBlock($b, new Sugarcane(), true, false, true);
$this->getLevel()->setBlock($b, new Sugarcane(), true);
break;
}
}
$this->meta = 0;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
}else{
++$this->meta;
$this->getLevel()->setBlock($this, $this, true, false, true);
$this->getLevel()->setBlock($this, $this, true);
}
return Level::BLOCK_UPDATE_RANDOM;
@ -103,7 +103,7 @@ class Sugarcane extends Flowable{
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::SUGARCANE_BLOCK){
$this->getLevel()->setBlock($block, new Sugarcane(), true, false, true);
$this->getLevel()->setBlock($block, new Sugarcane(), true);
return true;
}elseif($down->getID() === self::GRASS or $down->getID() === self::DIRT or $down->getID() === self::SAND){
@ -112,7 +112,7 @@ class Sugarcane extends Flowable{
$block2 = $down->getSide(4);
$block3 = $down->getSide(5);
if(($block0 instanceof Water) or ($block1 instanceof Water) or ($block2 instanceof Water) or ($block3 instanceof Water)){
$this->getLevel()->setBlock($block, new Sugarcane(), true, false, true);
$this->getLevel()->setBlock($block, new Sugarcane(), true);
return true;
}

View File

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

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