Compare commits

..

197 Commits

Author SHA1 Message Date
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
bf5630dc0d Fixed #1926 Teleport to non-generated chunks 2014-08-26 16:45:51 +02:00
472431752b Dropped items and arrows get deleted on Y < 0 2014-08-26 16:19:45 +02:00
c40f9f65a5 Optimize imports 2014-08-26 11:54:24 +02:00
f74af12914 Improved chunk ticking, enabled again. Disable it setting chunk-ticking.per-tick to 0 2014-08-26 11:52:45 +02:00
d169734781 Improved chunk sending 2014-08-26 11:50:51 +02:00
35b86af2af Fixed furnace achievement check 2014-08-26 10:56:33 +02:00
706bc8e8db Fixed undefined index on furnace recipes 2014-08-26 00:05:40 +02:00
b542c5b9bd Added Furnace progress fire 2014-08-26 00:05:18 +02:00
69800c6d79 Fixed #1911 Implemented FurnaceInventory callback 2014-08-26 00:03:16 +02:00
ea9fc3c72e Fixed #1879 Tile entities were not saved on chunk unload 2014-08-26 00:02:20 +02:00
8b90281355 Fixed #1953 Increased item PickupDelay to 2.5 seconds 2014-08-25 23:38:35 +02:00
92cabced97 Ctrl+C handling and kill signals are working again 2014-08-25 23:24:18 +02:00
cb645fa288 Moved spl to PocketMine-SPL 2014-08-25 21:02:33 +02:00
bda597a71e Moved spl to PocketMine-SPL 2014-08-25 20:54:53 +02:00
d6a0e284e3 Workaround BaseChunk::setBlock() recursion issues 2014-08-25 17:08:02 +02:00
1795c8c5e3 Fixed Chests/Furnaces not dropping contents when broken 2014-08-25 16:59:04 +02:00
c3b1b59118 Fixed #1970 Breaking blocks does not remove tile entities 2014-08-25 16:55:52 +02:00
a0df0a8fff Fixed player fall damage 2014-08-25 16:53:20 +02:00
049103ab7a Improved Block selection and construction performance 2014-08-25 16:39:47 +02:00
84c63c48ca Improved NBT IntArray read/write 2014-08-25 16:28:46 +02:00
20e11bd408 Improved player onGround collision check 2014-08-25 15:48:12 +02:00
456760b334 Removed unloaded chunk check 2014-08-25 15:43:48 +02:00
46e502430e Added teleport flag to MovePlayerPacket, improves player movement 2014-08-25 13:01:39 +02:00
87b800ebb9 Fixed #1967 Glowstone dust -> Glowstone recipe 2014-08-25 11:33:47 +02:00
9fdafb87b4 Fixed #1962 Fake client-side player entities 2014-08-24 23:12:12 +02:00
1fcfef20b0 Implemented beds 2014-08-24 20:34:24 +02:00
6109505786 Implemented correct time offsets and speed 2014-08-24 20:34:06 +02:00
764937dda4 Fixed #1961 2014-08-24 18:08:14 +02:00
8bf36315ae Updated RakLib 2014-08-24 17:21:05 +02:00
1ea0531ec7 Added RakLib port checking option 2014-08-24 17:16:37 +02:00
c47e359262 Updated blocks bounding boxes 2014-08-24 16:30:56 +02:00
f0f9bccb4b Fixed #1960 2014-08-24 15:57:13 +02:00
214dcef1ea Improved Air block collision check 2014-08-24 15:55:34 +02:00
4edadd764c Improved Level::getBlock() 2014-08-24 14:30:43 +02:00
01ebe74974 Performance improvements in blocks and Entities 2014-08-24 14:08:17 +02:00
84ce5f1c73 Performance improvements in NBT reading/writing 2014-08-24 13:59:37 +02:00
93a2bd36e0 Require PHP >= 5.5 2014-08-24 13:33:03 +02:00
fdd59e4506 Fixed default memory-limit values 2014-08-23 20:14:41 +02:00
9b86b1d45b Added --enable-profiler parameter to use with @krakjoe profiler 2014-08-23 20:14:04 +02:00
1a38003bc4 Fixed /version 2014-08-22 19:39:24 +02:00
60ea4d0e96 Removed hardcoded Server name from source 2014-08-22 18:31:17 +02:00
6077190a62 Deprecated Server::loadPlugin(Plugin) in favor of Server::enablePlugin(Plugin) 2014-08-22 17:43:29 +02:00
57299b9a29 Fixed #1948 /whitelist list is now working 2014-08-22 13:23:56 +02:00
bb08da701b Fixed header logo in PR #1944 2014-08-22 11:30:15 +02:00
ee593fe5e4 Merge pull request #1944 from PEMapModder/patch-2
Cleaned Mycelium.php and fixed its potential crash
2014-08-22 11:22:10 +02:00
e8b1b0fab6 Cleaned Mycelium.php and fixed its potential crash
Crash report: http://crash.pocketmine.net/view/27500
2014-08-22 11:05:47 +08:00
248 changed files with 4213 additions and 3932 deletions

3
.gitmodules vendored
View File

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

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.8
- 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

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

View File

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

View File

@ -43,7 +43,7 @@ class CrashDump{
$this->path = $this->server->getDataPath() . "CrashDump_" . date("D_M_j-H.i.s-T_Y", $this->time) . ".log";
$this->fp = fopen($this->path, "wb");
$this->data["time"] = $this->time;
$this->addLine("PocketMine-MP Crash Dump " . date("D M j H:i:s T Y", $this->time));
$this->addLine($this->server->getName() . " Crash Dump " . date("D M j H:i:s T Y", $this->time));
$this->addLine();
$this->baseCrash();
$this->generalData();
@ -137,7 +137,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 +153,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"];
@ -228,7 +228,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());

View File

@ -31,6 +31,7 @@ use pocketmine\entity\Living;
use pocketmine\event\block\SignChangeEvent;
use pocketmine\event\entity\EntityDamageByEntityEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityShootBowEvent;
use pocketmine\event\inventory\InventoryCloseEvent;
use pocketmine\event\inventory\InventoryPickupItemEvent;
use pocketmine\event\player\PlayerAchievementAwardedEvent;
@ -59,6 +60,7 @@ use pocketmine\inventory\InventoryHolder;
use pocketmine\inventory\SimpleTransactionGroup;
use pocketmine\inventory\StonecutterShapelessRecipe;
use pocketmine\item\Item;
use pocketmine\level\format\FullChunk;
use pocketmine\level\format\LevelProvider;
use pocketmine\level\Level;
use pocketmine\level\Position;
@ -138,7 +140,8 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
protected $isCrafting = false;
public $loginData = [];
protected $lastMovement = 0;
protected $forceMovement = false;
/** @var Vector3 */
protected $forceMovement = null;
protected $connected = true;
protected $ip;
protected $removeFormat = true;
@ -147,9 +150,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
protected $iusername;
protected $displayName;
protected $startAction = false;
/** @var Vector3|bool */
protected $sleeping = false;
protected $clientID = null;
protected $stepHeight = 0.5;
public $usedChunks = [];
protected $loadQueue = [];
protected $chunkACK = [];
@ -687,7 +693,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$chunkZ = $Z + $centerZ;
$index = Level::chunkHash($chunkX, $chunkZ);
if(!isset($this->usedChunks[$index])){
if($this->getLevel()->isChunkPopulated($chunkX, $chunkZ)){
if($this->level->isChunkPopulated($chunkX, $chunkZ)){
$newOrder[$index] = $distance;
}else{
$generateQueue->insert([$chunkX, $chunkZ], $distance);
@ -728,10 +734,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$entity->despawnFrom($this);
}
}
/*$pk = new UnloadChunkPacket();
$pk->chunkX = $X;
$pk->chunkZ = $Z;
$this->dataPacket($pk);*/
unset($this->usedChunks[$index]);
}
}
@ -805,11 +808,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
$this->sleeping = $pos;
$this->teleport(new Position($pos->x + 0.5, $pos->y + 1, $pos->z + 0.5, $this->getLevel()));
/*if($this->entity instanceof Entity){
$this->updateMetadata();
}*/
$this->sendMetadata($this->getViewers());
$this->sendMetadata($this);
$this->setSpawn($pos);
$this->tasks[] = $this->server->getScheduler()->scheduleDelayedTask(new CallbackTask(array($this, "checkSleep")), 60);
$this->tasks[] = $this->server->getScheduler()->scheduleDelayedTask(new CallbackTask([$this, "checkSleep"]), 60);
return true;
@ -836,9 +840,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
public function stopSleep(){
$this->sleeping = false;
//if($this->entity instanceof Entity){
//$this->entity->updateMetadata();
//}
$this->sendMetadata($this->getViewers());
$this->sendMetadata($this);
}
/**
@ -848,17 +852,22 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
public function checkSleep(){
if($this->sleeping !== false){
//TODO: Move to Level
/*if($this->server->api->time->getPhase($this->getLevel()) === "night"){
$time = $this->getLevel()->getTime() % Level::TIME_FULL;
if($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);{
foreach($this->getLevel()->getPlayers() as $p){
if($p->sleeping === false){
return;
}
}
$this->server->api->time->set("day", $this->getLevel());
$this->getLevel()->setTime($this->getLevel()->getTime() + Level::TIME_FULL - $time);
foreach($this->getLevel()->getPlayers() as $p){
$p->stopSleep();
}
}*/
}
}
return;
@ -973,7 +982,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$pk = new StartGamePacket;
$pk->seed = $this->getLevel()->getSeed();
$pk->x = $this->x;
$pk->y = $this->y + 1.62;
$pk->y = $this->y + $this->getEyeHeight();
$pk->z = $this->z;
$pk->spawnX = (int) $spawnPosition->x;
$pk->spawnY = (int) $spawnPosition->y;
@ -1032,7 +1041,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
0x80000000 ?
*/
$flags = 0;
if(($this->gamemode & 0x02) === 0x02){
if($this->isAdventure()){
$flags |= 0x01; //Do not allow placing/breaking blocks, adventure mode
}
@ -1045,6 +1054,26 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->dataPacket($pk);
}
public function isSurvival(){
return ($this->gamemode & 0x01) === 0;
}
public function isCreative(){
return ($this->gamemode & 0x01) > 0;
}
public function isAdventure(){
return ($this->gamemode & 0x02) > 0;
}
public function getDrops(){
if(!$this->isCreative()){
return parent::getDrops();
}
return [];
}
protected function getCreativeBlock(Item $item){
foreach(Block::$creative as $i => $d){
if($d[0] === $item->getID() and $d[1] === $item->getDamage()){
@ -1060,13 +1089,13 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
return true;
}
$hasUpdate = $this->entityBaseTick();
foreach($this->getLevel()->getNearbyEntities($this->boundingBox->expand(1, 1, 1), $this) as $entity){
foreach($this->getLevel()->getNearbyEntities($this->boundingBox->grow(1, 1, 1), $this) as $entity){
if($entity instanceof DroppedItem){
if($entity->dead !== true and $entity->getPickupDelay() <= 0){
$item = $entity->getItem();
if($item instanceof Item){
if(($this->gamemode & 0x01) === 0 and !$this->inventory->canAddItem($item)){
if($this->isSurvival() and !$this->inventory->canAddItem($item)){
continue;
}
@ -1130,7 +1159,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->displayName = $this->username;
$this->nameTag = $this->username;
$this->iusername = strtolower($this->username);
$this->loginData = array("clientId" => $packet->clientId, "loginData" => $packet->loginData);
$this->loginData = ["clientId" => $packet->clientId, "loginData" => $packet->loginData];
if(count($this->server->getOnlinePlayers()) > $this->server->getMaxPlayers()){
if($this->kick("server full") === true){
@ -1239,12 +1268,10 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
return;
}
if(($this->gamemode & 0x01) === 0x01){
if($this->isCreative()){
$this->inventory->setHeldItemSlot(0);
$this->inventory->setItemInHand(Item::get(Item::STONE, 0, 1));
}else{
$this->inventory->setHeldItemSlot(0);
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
}
$pk = new LoginStatusPacket;
@ -1292,9 +1319,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->orderChunks();
$this->tasks[] = $this->server->getScheduler()->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "orderChunks")), 10, 40);
$this->tasks[] = $this->server->getScheduler()->scheduleDelayedRepeatingTask(new CallbackTask([$this, "orderChunks"]), 10, 40);
$this->sendNextChunk();
$this->tasks[] = $this->chunkLoadTask = $this->server->getScheduler()->scheduleRepeatingTask(new CallbackTask(array($this, "sendNextChunk")), 1);
$this->tasks[] = $this->chunkLoadTask = $this->server->getScheduler()->scheduleRepeatingTask(new CallbackTask([$this, "sendNextChunk"]), 1);
break;
case ProtocolInfo::ROTATE_HEAD_PACKET:
@ -1309,44 +1336,73 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
$newPos = new Vector3($packet->x, $packet->y, $packet->z);
/*if($this->forceMovement instanceof Vector3){
if($this->forceMovement->distance($newPos) <= 0.7){
$this->forceMovement = false;
}else{
$this->setPosition($this->forceMovement);
}
}*/
/*$speed = $this->entity->getSpeedMeasure();
if($this->blocked === true or ($this->server->api->getProperty("allow-flight") !== true and (($speed > 9 and ($this->gamemode & 0x01) === 0x00) or $speed > 20 or $this->entity->distance($newPos) > 7)) or $this->server->api->handle("player.move", $this->entity) === false){
if($this->lastCorrect instanceof Vector3){
$this->teleport($this->lastCorrect, $this->entity->yaw, $this->entity->pitch, false);
}
if($this->blocked !== true){
$this->server->getLogger()->warning($this->username." moved too quickly!");
}
}else{*/
$oldPos = new Vector3($this->x, $this->y, $this->z);
$dy = $newPos->y - $this->y;
$revert = false;
if(count($this->getLevel()->getCollisionBlocks($this->boundingBox->getOffsetBoundingBox(0, $dy - 0.1, 0))) > 0){
$isColliding = true;
if($this->forceMovement instanceof Vector3 and $newPos->distance($this->forceMovement) > 0.1){
$revert = true;
}elseif($newPos->distance($this) > 100){
$this->server->getLogger()->warning($this->getName()." moved too quickly!");
$revert = true;
}else{
$isColliding = false;
if($this->chunk === null or !$this->chunk->isGenerated()){
$chunk = $this->getLevel()->getChunkAt($newPos->x >> 4, $newPos->z >> 4);
if(!($chunk instanceof FullChunk) or !$chunk->isGenerated()){
$revert = true;
}
}
}
$this->onGround = ($dy <= 0 and $isColliding);
$this->updateFallState($dy, $this->onGround);
if(!$revert){
$dx = $newPos->x - $this->x;
$dy = $newPos->y - $this->y;
$dz = $newPos->z - $this->z;
if(!$this->setPositionAndRotation($newPos, $packet->yaw, $packet->pitch)){
$packet->yaw %= 360;
$packet->pitch %= 360;
if($packet->yaw < 0){
$packet->yaw += 360;
}
if($packet->pitch < 0){
$packet->pitch += 360;
}
$this->setRotation($packet->yaw, $packet->pitch);
//$this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z);
$revert = !$this->move($dx, $dy, $dz);
$diffX = $this->x - $newPos->x;
$diffZ = $this->z - $newPos->z;
$diffY = $this->y - $newPos->y;
if($diffY > -0.5 or $diffY < 0.5){
$diffY = 0;
}
$diff = $diffX ** 2 + $diffY ** 2 + $diffZ ** 2;
if(!$revert and $diff > 0.0625 and !$this->isSleeping() and $this->isSurvival()){
$revert = true;
$this->server->getLogger()->warning($this->getName()." moved wrongly!");
}
}
if($revert){
$pk = new MovePlayerPacket();
$pk->eid = 0;
$pk->x = $this->x;
$pk->y = $this->y + $this->height; //teleport from head
$pk->y = $this->y + $this->getEyeHeight();
$pk->z = $this->z;
$pk->bodyYaw = $this->yaw;
$pk->pitch = $this->pitch;
$pk->yaw = $this->yaw;
$pk->teleport = true;
$this->directDataPacket($pk);
$this->forceMovement = new Vector3($this->x, $this->y, $this->z);
}else{
$this->forceMovement = null;
}
break;
@ -1361,7 +1417,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$packet->slot -= 9; //Get real block slot
}
if(($this->gamemode & 0x01) === 1){ //Creative mode match
if($this->isCreative()){ //Creative mode match
$item = Item::get($packet->item, $packet->meta, 1);
$slot = $this->getCreativeBlock($item);
}else{
@ -1370,7 +1426,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
if($packet->slot === -1){ //Air
if(($this->gamemode & 0x01) === Player::CREATIVE){
if($this->isCreative()){
$found = false;
for($i = 0; $i < $this->inventory->getHotbarSize(); ++$i){
if($this->inventory->getHotbarSlotIndex($i) === -1){
@ -1390,7 +1446,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}elseif(!isset($item) or $slot === -1 or $item->getID() !== $packet->item or $item->getDamage() !== $packet->meta){ // packet error or not implemented
$this->inventory->sendContents($this);
break;
}elseif(($this->gamemode & 0x01) === Player::CREATIVE){
}elseif($this->isCreative()){
$item = Item::get(
Block::$creative[$slot][0],
Block::$creative[$slot][1],
@ -1405,7 +1461,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
if($this->inAction === true){
$this->inAction = false;
//$this->entity->updateMetadata();
$this->sendMetadata($this->getViewers());
}
break;
case ProtocolInfo::USE_ITEM_PACKET:
@ -1440,12 +1496,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
if($packet->face >= 0 and $packet->face <= 5){ //Use Block, place
if($this->inAction === true){
$this->inAction = false;
//$this->entity->updateMetadata();
$this->sendMetadata($this->getViewers());
}
if($blockVector->distance($this) > 10){
}elseif(($this->gamemode & 0x01) === 1){
}elseif($this->isCreative()){
$item = $this->inventory->getItemInHand();
if($this->getLevel()->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){
break;
@ -1484,7 +1540,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
//TODO: add event
$this->inAction = true;
$this->startAction = microtime(true);
//$this->updateMetadata();
$this->sendMetadata($this->getViewers());
}
break;
case ProtocolInfo::PLAYER_ACTION_PACKET:
@ -1499,11 +1555,19 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
case 5: //Shot arrow
//if($this->entity->inAction === true){
if($this->inventory->getItemInHand()->getID() === Item::BOW){
$f = 1 * 2 * 1.5;
$bow = $this->inventory->getItemInHand();
if($this->isSurvival()){
if(!$this->inventory->contains(Item::get(Item::ARROW, 0, 1))){
$this->inventory->sendContents($this);
return;
}
}
$f = 1.5;
$nbt = new Compound("", [
"Pos" => new Enum("Pos", [
new Double("", $this->x),
new Double("", $this->y + 1.62),
new Double("", $this->y + $this->getEyeHeight()),
new Double("", $this->z)
]),
"Motion" => new Enum("Motion", [
@ -1516,13 +1580,30 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
new Float("", $this->pitch)
]),
]);
$arrow = new Arrow($this->chunk, $nbt);
$arrow->spawnToAll();
$arrow = new Arrow($this->chunk, $nbt, $this);
$ev = new EntityShootBowEvent($this, $bow, $arrow, $f);
$this->server->getPluginManager()->callEvent($ev);
if($ev->isCancelled()){
$arrow->kill();
}else{
if($this->isSurvival()){
$this->inventory->removeItem(Item::get(Item::ARROW, 0, 1));
$bow->setDamage($bow->getDamage() + 1);
$this->inventory->setItemInHand($bow);
if($bow->getDamage() >= 385){
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 0));
}
}
$arrow->spawnToAll();
}
}
//}
$this->startAction = false;
//$this->entity->inAction = false;
//$this->entity->updateMetadata();
$this->inAction = false;
$this->sendMetadata($this->getViewers());
break;
case 6: //get out of the bed
$this->stopSleep();
@ -1538,14 +1619,14 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$vector = new Vector3($packet->x, $packet->y, $packet->z);
if(($this->gamemode & 0x01) === 1){
if($this->isCreative()){
$item = $this->inventory->getItemInHand();
}else{
$item = clone $this->inventory->getItemInHand();
}
if($this->getLevel()->useBreakOn($vector, $item, $this) === true){
if(($this->gamemode & 0x01) === 0){
if($this->isSurvival()){
$this->inventory->setItemInHand($item);
$this->inventory->sendHeldItem($this->hasSpawned);
}
@ -1600,7 +1681,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
if($this->inAction === true){
$this->inAction = false;
//$this->entity->updateMetadata();
$this->sendMetadata($this->getViewers());
}
break;
case ProtocolInfo::INTERACT_PACKET:
@ -1623,6 +1704,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
if($target instanceof Entity and $this->getGamemode() !== Player::VIEW and $this->blocked === false and $this->dead !== true and $target->dead !== true){
if($target instanceof DroppedItem or $target instanceof Arrow){
$this->kick("Attempting to attack an invalid entity");
$this->server->getLogger()->warning("Player ". $this->getName() ." tried to attack an invalid entity");
return;
}
$item = $this->inventory->getItemInHand();
$damageTable = [
Item::WOODEN_SWORD => 4,
@ -1701,7 +1788,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
$this->server->getPluginManager()->callEvent($ev);
if($ev->isCancelled()){
if($item->isTool() and ($this->gamemode & 0x01) === 0){
if($item->isTool() and $this->isSurvival()){
$this->inventory->sendContents($this);
}
break;
@ -1709,7 +1796,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$target->attack($ev->getFinalDamage(), $ev);
if($item->isTool() and ($this->gamemode & 0x01) === 0){
if($item->isTool() and $this->isSurvival()){
if($item->useOn($target) and $item->getDamage() >= $item->getMaxDurability()){
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
}
@ -1743,12 +1830,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->server->getPluginManager()->callEvent($ev = new PlayerRespawnEvent($this, $this->getSpawn()));
$this->teleport($ev->getRespawnPosition());
//$this->entity->fire = 0;
//$this->entity->air = 300;
$this->fireTicks = 0;
$this->airTicks = 300;
$this->setHealth(20);
$this->dead = false;
//$this->entity->updateMetadata();
$this->sendMetadata($this->getViewers());
$this->sendSettings();
$this->inventory->sendContents($this);
@ -1768,11 +1855,11 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
if($this->inAction === true){
$this->inAction = false;
//$this->updateMetadata();
$this->sendMetadata($this->getViewers());
}
switch($packet->event){
case 9: //Eating
$items = array(
$items = [
Item::APPLE => 4,
Item::MUSHROOM_STEW => 10,
Item::BEETROOT_SOUP => 10,
@ -1792,7 +1879,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
//Item::COOKIE => 2,
//Item::COOKED_FISH => 5,
//Item::RAW_FISH => 2,
);
];
$slot = $this->inventory->getItemInHand();
if($this->getHealth() < 20 and isset($items[$slot->getID()])){
$this->server->getPluginManager()->callEvent($ev = new PlayerItemConsumeEvent($this, $slot));
@ -1832,13 +1919,13 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
$this->inventory->setItemInHand(Item::get(Item::AIR, 0, 1));
$motion = $this->getDirectionVector()->multiply(10);
$motion = $this->getDirectionVector()->multiply(0.4);
$this->getLevel()->dropItem($this->add(0, 1, 0), $item, $motion);
$this->getLevel()->dropItem($this->add(0, 1.3, 0), $item, $motion, 40);
if($this->inAction === true){
$this->inAction = false;
//$this->updateMetadata();
$this->sendMetadata($this->getViewers());
}
break;
case ProtocolInfo::MESSAGE_PACKET:
@ -1891,13 +1978,13 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
if($packet->slot > $this->inventory->getSize()){
break;
}
if(($this->gamemode & 0x01) === Player::CREATIVE){
if($this->isCreative()){
if($this->getCreativeBlock($packet->item) !== -1){
$this->inventory->setItem($packet->slot, $packet->item);
$this->inventory->setHotbarSlotIndex($packet->slot, $packet->slot); //links $hotbar[$packet->slot] to $slots[$packet->slot]
}
}else{
$this->inventory->setHeldItemSlot($packet->slot);
}
$transaction = new BaseTransaction($this->inventory, $packet->slot, $this->inventory->getItem($packet->slot), $packet->item);
}elseif(isset($this->windowIndex[$packet->windowid])){
@ -1935,7 +2022,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$inv = $ts->getInventory();
if($inv instanceof FurnaceInventory){
if($ts->getSlot() === 2){
switch($inv->getResult()){
switch($inv->getResult()->getID()){
case Item::IRON_INGOT:
$this->awardAchievement("acquireIron");
break;
@ -2110,7 +2197,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->tasks = [];
if($this->connected === true){
parent::close();
if($this->username != ""){
$this->server->getPluginManager()->callEvent($ev = new PlayerQuitEvent($this, $message));
if($this->loggedIn === true){
@ -2120,8 +2206,11 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->connected = false;
$this->interface->close($this, $reason);
$this->server->removePlayer($this);
$this->getLevel()->freeAllChunks($this);
parent::close();
$this->loggedIn = false;
if(isset($ev) and $this->username != "" and $this->spawned !== false and $ev->getQuitMessage() != ""){
@ -2136,30 +2225,38 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->loadQueue = [];
unset($this->buffer);
}
$this->server->removePlayer($this);
}
/**
* Handles player data saving
*/
public function save(){
if($this->closed){
throw new \Exception("Tried to save closed player");
}
parent::saveNBT();
$this->namedtag["Level"] = $this->getLevel()->getName();
if($this->spawnPosition instanceof Position and $this->spawnPosition->getLevel() instanceof Level){
$this->namedtag["SpawnLevel"] = $this->spawnPosition->getLevel()->getName();
$this->namedtag["SpawnX"] = (int) $this->spawnPosition->x;
$this->namedtag["SpawnY"] = (int) $this->spawnPosition->y;
$this->namedtag["SpawnZ"] = (int) $this->spawnPosition->z;
}
if($this->getLevel() instanceof Level){
$this->namedtag["Level"] = $this->getLevel()->getName();
if($this->spawnPosition instanceof Position and $this->spawnPosition->getLevel() instanceof Level){
$this->namedtag["SpawnLevel"] = $this->spawnPosition->getLevel()->getName();
$this->namedtag["SpawnX"] = (int) $this->spawnPosition->x;
$this->namedtag["SpawnY"] = (int) $this->spawnPosition->y;
$this->namedtag["SpawnZ"] = (int) $this->spawnPosition->z;
}
foreach($this->achievements as $achievement => $status){
$this->namedtag->Achievements[$achievement] = new Byte($achievement, $status === true ? 1 : 0);
}
foreach($this->achievements as $achievement => $status){
$this->namedtag->Achievements[$achievement] = new Byte($achievement, $status === true ? 1 : 0);
}
$this->namedtag["playerGameType"] = $this->gamemode;
$this->namedtag["lastPlayed"] = floor(microtime(true) * 1000);
$this->namedtag["playerGameType"] = $this->gamemode;
$this->namedtag["lastPlayed"] = floor(microtime(true) * 1000);
if($this->username != "" and $this->isOnline() and $this->namedtag instanceof Compound){
$this->server->saveOfflinePlayerData($this->username, $this->namedtag);
if($this->username != "" and $this->isOnline() and $this->namedtag instanceof Compound){
$this->server->saveOfflinePlayerData($this->username, $this->namedtag);
}
}
}
@ -2204,8 +2301,18 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
$message = $this->getName() . " was killed";
break;
case EntityDamageEvent::CAUSE_PROJECTILE:
if($ev instanceof EntityDamageByEntityEvent){
$e = $ev->getDamager();
if($e instanceof Living){
$message = $this->getName() . " was shot by " . $e->getName();
break;
}
}
$message = $this->getName() . " was shot by arrow";
break;
case EntityDamageEvent::CAUSE_SUICIDE:
$message = $this->getName() . " died";
break;
case EntityDamageEvent::CAUSE_VOID:
$message = $this->getName() . " fell out of the world";
@ -2220,13 +2327,30 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$message = $this->getName() . " hit the ground too hard";
break;
case EntityDamageEvent::CAUSE_CONTACT:
case EntityDamageEvent::CAUSE_PROJECTILE:
case EntityDamageEvent::CAUSE_SUFFOCATION:
case EntityDamageEvent::CAUSE_FIRE:
case EntityDamageEvent::CAUSE_FIRE_TICK:
$message = $this->getName() . " suffocated in a wall";
break;
case EntityDamageEvent::CAUSE_LAVA:
$message = $this->getName() . " tried to swim in lava";
break;
case EntityDamageEvent::CAUSE_FIRE:
$message = $this->getName() . " went up in flames";
break;
case EntityDamageEvent::CAUSE_FIRE_TICK:
$message = $this->getName() . " burned to death";
break;
case EntityDamageEvent::CAUSE_DROWNING:
$message = $this->getName() . " drowned";
break;
case EntityDamageEvent::CAUSE_CONTACT:
$message = $this->getName() . " was pricked to death";
break;
case EntityDamageEvent::CAUSE_BLOCK_EXPLOSION:
case EntityDamageEvent::CAUSE_ENTITY_EXPLOSION:
case EntityDamageEvent::CAUSE_MAGIC:
@ -2238,7 +2362,9 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$this->server->getPluginManager()->callEvent($ev = new PlayerDeathEvent($this, $this->getDrops(), $message));
$this->server->broadcast($ev->getDeathMessage(), Server::BROADCAST_CHANNEL_USERS);
if($ev->getDeathMessage() != ""){
$this->server->broadcast($ev->getDeathMessage(), Server::BROADCAST_CHANNEL_USERS);
}
}
@ -2271,11 +2397,37 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
}
}
$pk = new EntityEventPacket();
$pk->eid = 0;
$pk->event = 2;
$this->dataPacket($pk);
parent::attack($damage, $source);
if($this->getLastDamageCause() === $source){
$pk = new EntityEventPacket();
$pk->eid = 0;
$pk->event = 2;
$this->dataPacket($pk);
}
}
public function getData(){ //TODO
$flags = 0;
$flags |= $this->fireTicks > 0 ? 1 : 0;
//$flags |= ($this->crouched === true ? 0b10:0) << 1;
$flags |= ($this->inAction === true ? 0b10000:0);
$d = [
0 => ["type" => 0, "value" => $flags],
1 => ["type" => 1, "value" => $this->airTicks],
16 => ["type" => 0, "value" => 0],
17 => ["type" => 6, "value" => [0, 0, 0]],
];
if($this->sleeping !== false){
$d[16]["value"] = 2;
$d[17]["value"] = [$this->sleeping->x, $this->sleeping->y, $this->sleeping->z];
}
return $d;
}
public function teleport(Vector3 $pos, $yaw = null, $pitch = null){
@ -2289,11 +2441,12 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$pk = new MovePlayerPacket;
$pk->eid = 0;
$pk->x = $this->x;
$pk->y = $this->y + 1.62; //teleport from head
$pk->y = $this->y + $this->getEyeHeight();
$pk->z = $this->z;
$pk->bodyYaw = $this->yaw;
$pk->pitch = $this->pitch;
$pk->yaw = $this->yaw;
$pk->teleport = true;
$this->directDataPacket($pk);
}
}

View File

@ -73,7 +73,7 @@ namespace pocketmine {
use raklib\RakLib;
const VERSION = "Alpha_1.4dev";
const API_VERSION = "1.3.0";
const API_VERSION = "1.4.0";
const CODENAME = "絶好(Zekkou)ケーキ(Cake)";
const MINECRAFT_VERSION = "v0.9.5 alpha";
@ -89,21 +89,17 @@ namespace pocketmine {
exit(1);
}
if(!class_exists("SplClassLoader", false)){
require_once(\pocketmine\PATH . "src/spl/SplClassLoader.php");
if(!class_exists("ClassLoader", false)){
require_once(\pocketmine\PATH . "src/spl/ClassLoader.php");
require_once(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
require_once(\pocketmine\PATH . "src/pocketmine/CompatibleClassLoader.php");
}
$autoloader = new \SplClassLoader();
$autoloader->setMode(\SplAutoloader::MODE_DEBUG);
$autoloader->add("pocketmine", [
\pocketmine\PATH . "src"
]);
$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
@ -120,10 +116,10 @@ namespace pocketmine {
$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;
$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;
$offset = @round((intval(trim($t[0])) - time()) / 60) * 60;
}
$daylight = (int) date("I");
@ -149,7 +145,7 @@ 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"));
$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);
@ -158,6 +154,15 @@ namespace pocketmine {
$logger = new MainLogger(\pocketmine\DATA . "server.log", \pocketmine\ANSI);
if(isset($opts["enable-profiler"])){
if(function_exists("profiler_enable")){
\profiler_enable();
$logger->notice("Execution is being profiled");
}else{
$logger->notice("No profiler found. Please install https://github.com/krakjoe/profiler");
}
}
function kill($pid){
switch(Utils::getOS()){
case "win":
@ -209,7 +214,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",
@ -225,7 +230,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){
@ -255,8 +260,8 @@ namespace pocketmine {
$errors = 0;
if(version_compare("5.4.0", PHP_VERSION) > 0){
$logger->critical("Use PHP >= 5.4.0");
if(version_compare("5.6.0", PHP_VERSION) > 0){
$logger->critical("You must use PHP >= 5.6");
++$errors;
}
@ -274,8 +279,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

@ -61,7 +61,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;
@ -128,9 +127,8 @@ 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;
@ -455,7 +453,7 @@ class Server{
}
/**
* @return \SplClassLoader
* @return \ClassLoader
*/
public function getLoader(){
return $this->autoloader;
@ -537,7 +535,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 +633,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 +650,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 +685,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 +795,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 +809,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;
}
}
}
/**
@ -1048,12 +1060,8 @@ class Server{
if($generator !== null and class_exists($generator) and is_subclass_of($generator, "pocketmine\\level\\generator\\Generator")){
$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){
@ -1142,7 +1150,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 +1200,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 +1223,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{
@ -1377,13 +1385,13 @@ class Server{
}
/**
* @param \SplClassLoader $autoloader
* @param \ClassLoader $autoloader
* @param \ThreadedLogger $logger
* @param string $filePath
* @param string $dataPath
* @param string $pluginPath
*/
public function __construct(\SplClassLoader $autoloader, \ThreadedLogger $logger, $filePath, $dataPath, $pluginPath){
public function __construct(\ClassLoader $autoloader, \ThreadedLogger $logger, $filePath, $dataPath, $pluginPath){
self::$instance = $this;
$this->autoloader = $autoloader;
@ -1427,7 +1435,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 +1459,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);
@ -1463,15 +1471,15 @@ class Server{
$this->maxPlayers = $this->getConfigInt("max-players", 20);
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "128M")))) !== false){
$value = array("M" => 1, "G" => 1024);
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "256M")))) !== false){
$value = ["M" => 1, "G" => 1024];
$real = ((int) substr($memory, 0, -1)) * $value[substr($memory, -1)];
if($real < 128){
$this->logger->warning("PocketMine-MP may not work right with less than 128MB of RAM", true, true, 0);
$this->logger->warning($this->getName() . " may not work right with less than 128MB of RAM", true, true, 0);
}
@ini_set("memory_limit", $memory);
}else{
$this->setConfigString("memory-limit", "128M");
$this->setConfigString("memory-limit", "256M");
}
if($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3){
@ -1489,8 +1497,8 @@ class Server{
Level::$COMPRESSION_LEVEL = $this->getProperty("chunk-sending.compression-level", 7);
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0 and function_exists("cli_set_process_title")){
@cli_set_process_title("PocketMine-MP " . $this->getPocketMineVersion());
if(defined("pocketmine\\DEBUG") and \pocketmine\DEBUG >= 0){
@cli_set_process_title($this->getName() . " " . $this->getPocketMineVersion());
}
$this->logger->info("Starting Minecraft PE server on " . ($this->getIp() === "" ? "*" : $this->getIp()) . ":" . $this->getPort());
@ -1499,8 +1507,11 @@ class Server{
$this->addInterface($this->mainInterface = new RakLibInterface($this));
$this->logger->info("This server is running PocketMine-MP version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(false) . TextFormat::RESET . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0);
$this->logger->info("PocketMine-MP is distributed under the LGPL License", true, true, 0);
$this->logger->info("This server is running " . $this->getName() . " version " . ($version->isDev() ? TextFormat::YELLOW : "") . $version->get(false) . TextFormat::RESET . " \"" . $this->getCodename() . "\" (API " . $this->getApiVersion() . ")", true, true, 0);
$this->logger->info($this->getName() . " is distributed under the LGPL License", true, true, 0);
PluginManager::$pluginParentTimer = new TimingsHandler("** Plugins");
Timings::init();
$this->consoleSender = new ConsoleCommandSender();
$this->commandMap = new SimpleCommandMap($this);
@ -1510,9 +1521,6 @@ 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));
@ -1538,6 +1546,13 @@ class Server{
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "normal");
Generator::addGenerator("pocketmine\\level\\generator\\Normal", "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){
$seed = $this->getProperty("worlds.$name.seed", time());
@ -1558,7 +1573,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");
}
@ -1582,7 +1597,7 @@ class Server{
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask("pocketmine\\utils\\Cache::cleanup"), $this->getProperty("ticks-per.cache-cleanup", 900), $this->getProperty("ticks-per.cache-cleanup", 900));
if($this->getConfigBoolean("auto-save", true) === true and $this->getProperty("ticks-per.autosave", 6000) > 0){
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask(array($this, "doAutoSave")), $this->getProperty("ticks-per.autosave", 6000), $this->getProperty("ticks-per.autosave", 6000));
$this->scheduler->scheduleDelayedRepeatingTask(new CallbackTask([$this, "doAutoSave"]), $this->getProperty("ticks-per.autosave", 6000), $this->getProperty("ticks-per.autosave", 6000));
}
if($this->getProperty("chunk-gc.period-in-ticks", 600) > 0){
@ -1646,7 +1661,7 @@ class Server{
public function enablePlugins($type){
foreach($this->pluginManager->getPlugins() as $plugin){
if(!$plugin->isEnabled() and $plugin->getDescription()->getOrder() === $type){
$this->loadPlugin($plugin);
$this->enablePlugin($plugin);
}
}
@ -1659,10 +1674,19 @@ class Server{
/**
* @param Plugin $plugin
*/
public function loadPlugin(Plugin $plugin){
public function enablePlugin(Plugin $plugin){
$this->pluginManager->enablePlugin($plugin);
}
/**
* @param Plugin $plugin
*
* @deprecated
*/
public function loadPlugin(Plugin $plugin){
$this->enablePlugin($plugin);
}
public function disablePlugins(){
$this->pluginManager->disablePlugins();
}
@ -1716,14 +1740,14 @@ class Server{
$this->maxPlayers = $this->getConfigInt("max-players", 20);
if(($memory = str_replace("B", "", strtoupper($this->getConfigString("memory-limit", "256M")))) !== false){
$value = array("M" => 1, "G" => 1024);
$value = ["M" => 1, "G" => 1024];
$real = ((int) substr($memory, 0, -1)) * $value[substr($memory, -1)];
if($real < 256){
$this->logger->warning("PocketMine-MP may not work right with less than 256MB of RAM", true, true, 0);
$this->logger->warning($this->getName() . " may not work right with less than 256MB of RAM", true, true, 0);
}
@ini_set("memory_limit", $memory);
}else{
$this->setConfigString("memory-limit", "128M");
$this->setConfigString("memory-limit", "256M");
}
if($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3){
@ -1800,7 +1824,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();
}
@ -1813,12 +1837,16 @@ class Server{
$this->tickCounter = 0;
if(function_exists("pcntl_signal")){
pcntl_signal(SIGTERM, array($this, "shutdown"));
pcntl_signal(SIGINT, array($this, "shutdown"));
pcntl_signal(SIGHUP, array($this, "shutdown"));
pcntl_signal(SIGTERM, [$this, "handleSignal"]);
pcntl_signal(SIGINT, [$this, "handleSignal"]);
pcntl_signal(SIGHUP, [$this, "handleSignal"]);
$this->getScheduler()->scheduleRepeatingTask(new CallbackTask("pcntl_signal_dispatch"), 5);
}
$this->logger->info("Default game type: " . self::getGamemodeString($this->getGamemode())); //TODO: string name
$this->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 "?"');
@ -1828,6 +1856,12 @@ class Server{
gc_collect_cycles();
}
public function handleSignal($signo){
if($signo === SIGTERM or $signo === SIGINT or $signo === SIGHUP){
$this->shutdown();
}
}
public function checkTicks(){
if($this->getTicksPerSecond() < 12){
$this->logger->warning("Can't keep up! Is the server overloaded?");
@ -1878,13 +1912,14 @@ class Server{
}
}elseif(\Phar::running(true) == ""){
return;
}elseif($dump->getData()["type"] === "E_PARSE" or $dump->getData()["type"] === "E_COMPILE_ERROR"){
}
if($dump->getData()["type"] === "E_PARSE" or $dump->getData()["type"] === "E_COMPILE_ERROR"){
return;
}
$reply = Utils::postURL("http://" . $this->getProperty("auto-report.host", "crash.pocketmine.net") . "/submit/api", [
"report" => "yes",
"name" => "PocketMine-MP " . $this->getPocketMineVersion(),
"name" => $this->getName() . " " . $this->getPocketMineVersion(),
"email" => "crash@pocketmine.net",
"reportPaste" => base64_encode($dump->getEncodedData())
]);
@ -1901,31 +1936,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));
}
}
@ -1935,32 +1954,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);
@ -1968,10 +1961,13 @@ class Server{
}
public function doAutoSave(){
Timings::$worldSaveTimer->startTiming();
foreach($this->getOnlinePlayers() as $player){
$player->save();
foreach($this->getOnlinePlayers() as $index => $player){
if($player->isOnline()){
$player->save();
}elseif(!$player->isConnected()){
unset($this->players[$index]);
}
}
foreach($this->getLevels() as $level){
@ -1992,14 +1988,15 @@ 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(
$this->lastSendUsage = new SendUsageTask("http://stats.pocketmine.net/usage.php", [
"serverid" => Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() . ":" . $this->getPort()), 0, 8)),
"port" => $this->getPort(),
"os" => Utils::getOS(),
@ -2013,14 +2010,14 @@ class Server{
"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;PocketMine-MP " . $this->getPocketMineVersion() . " | Online " . count($this->players) . "/" . $this->getMaxPlayers() . " | RAM " . round((memory_get_usage() / 1024) / 1024, 2) . "/" . round((memory_get_usage(true) / 1024) / 1024, 2) . " MB | U " . 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";
}
}
@ -2028,44 +2025,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->handlePackets();
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

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

View File

@ -22,6 +22,8 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\network\protocol\ChatPacket;
use pocketmine\Player;
@ -33,14 +35,30 @@ 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){
/*if($player instanceof Player and Server::getInstance()->api->time->getPhase($this->getLevel()) !== "night"){
$time = $this->getLevel()->getTime() % Level::TIME_FULL;
$isNight = ($time >= Level::TIME_NIGHT and $time < Level::TIME_SUNRISE);
if($player instanceof Player and !$isNight){
$pk = new ChatPacket;
$pk->message = "You can only sleep at night";
$player->dataPacket($pk);
return true;
}*/
}
$blockNorth = $this->getSide(2); //Gets the blocks around them
$blockSouth = $this->getSide(3);
@ -57,10 +75,12 @@ class Bed extends Transparent{
$b = $blockEast;
}elseif($blockWest->getID() === $this->id and ($blockWest->meta & 0x08) === 0x08){
$b = $blockWest;
}elseif($player instanceof Player){
$pk = new ChatPacket;
$pk->message = "This bed is incomplete";
$player->dataPacket($pk);
}else{
if($player instanceof Player){
$pk = new ChatPacket;
$pk->message = "This bed is incomplete";
$player->dataPacket($pk);
}
return true;
}
@ -78,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;
}
@ -107,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

@ -32,10 +32,14 @@ class Beetroot extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -46,7 +50,7 @@ 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->getLevel()->setBlock($this, $this, true, true);
$item->count--;
return true;
@ -59,7 +63,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;
}
@ -67,7 +71,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;
}
@ -82,10 +86,10 @@ class Beetroot extends Flowable{
public function getDrops(Item $item){
$drops = [];
if($this->meta >= 0x07){
$drops[] = array(Item::BEETROOT, 0, 1);
$drops[] = array(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3));
$drops[] = [Item::BEETROOT, 0, 1];
$drops[] = [Item::BEETROOT_SEEDS, 0, mt_rand(0, 3)];
}else{
$drops[] = array(Item::BEETROOT_SEEDS, 0, 1);
$drops[] = [Item::BEETROOT_SEEDS, 0, 1];
}
return $drops;

View File

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

View File

@ -24,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,15 +503,15 @@ abstract class Block extends Position implements Metadatable{
[Item::DYE, 9],
[Item::DYE, 8],
);
];
/** @var Block[] */
public static $list = [];
protected $id;
protected $meta;
protected $name;
protected $breakTime;
protected $hardness;
protected $name = "Unknown";
protected $breakTime = 0.20;
protected $hardness = 10;
public $isActivable = false;
public $breakable = true;
public $isFlowable = false;
@ -526,144 +529,144 @@ abstract class Block extends Position implements Metadatable{
public static function init(){
if(count(self::$list) === 0){
self::$list = array(
self::AIR => new Air(),
self::STONE => new Stone(),
self::GRASS => new Grass(),
self::DIRT => new Dirt(),
self::COBBLESTONE => new Cobblestone(),
self::PLANKS => new Planks(),
self::SAPLING => new Sapling(),
self::BEDROCK => new Bedrock(),
self::WATER => new Water(),
self::STILL_WATER => new StillWater(),
self::LAVA => new Lava(),
self::STILL_LAVA => new StillLava(),
self::SAND => new Sand(),
self::GRAVEL => new Gravel(),
self::GOLD_ORE => new GoldOre(),
self::IRON_ORE => new IronOre(),
self::COAL_ORE => new CoalOre(),
self::WOOD => new Wood(),
self::LEAVES => new Leaves(),
self::SPONGE => new Sponge(),
self::GLASS => new Glass(),
self::LAPIS_ORE => new LapisOre(),
self::LAPIS_BLOCK => new Lapis(),
self::SANDSTONE => new Sandstone(),
self::BED_BLOCK => new Bed(),
self::COBWEB => new Cobweb(),
self::TALL_GRASS => new TallGrass(),
self::DEAD_BUSH => new DeadBush(),
self::WOOL => new Wool(),
self::DANDELION => new Dandelion(),
self::POPPY => new CyanFlower(),
self::BROWN_MUSHROOM => new BrownMushroom(),
self::RED_MUSHROOM => new RedMushroom(),
self::GOLD_BLOCK => new Gold(),
self::IRON_BLOCK => new Iron(),
self::DOUBLE_SLAB => new DoubleSlab(),
self::SLAB => new Slab(),
self::BRICKS_BLOCK => new Bricks(),
self::TNT => new TNT(),
self::BOOKSHELF => new Bookshelf(),
self::MOSS_STONE => new MossStone(),
self::OBSIDIAN => new Obsidian(),
self::TORCH => new Torch(),
self::FIRE => new Fire(),
self::MONSTER_SPAWNER => new MonsterSpawner(),
self::WOOD_STAIRS => new WoodStairs(),
self::CHEST => new Chest(),
self::$list = [
self::AIR => Air::class,
self::STONE => Stone::class,
self::GRASS => Grass::class,
self::DIRT => Dirt::class,
self::COBBLESTONE => Cobblestone::class,
self::PLANKS => Planks::class,
self::SAPLING => Sapling::class,
self::BEDROCK => Bedrock::class,
self::WATER => Water::class,
self::STILL_WATER => StillWater::class,
self::LAVA => Lava::class,
self::STILL_LAVA => StillLava::class,
self::SAND => Sand::class,
self::GRAVEL => Gravel::class,
self::GOLD_ORE => GoldOre::class,
self::IRON_ORE => IronOre::class,
self::COAL_ORE => CoalOre::class,
self::WOOD => Wood::class,
self::LEAVES => Leaves::class,
self::SPONGE => Sponge::class,
self::GLASS => Glass::class,
self::LAPIS_ORE => LapisOre::class,
self::LAPIS_BLOCK => Lapis::class,
self::SANDSTONE => Sandstone::class,
self::BED_BLOCK => Bed::class,
self::COBWEB => Cobweb::class,
self::TALL_GRASS => TallGrass::class,
self::DEAD_BUSH => DeadBush::class,
self::WOOL => Wool::class,
self::DANDELION => Dandelion::class,
self::POPPY => CyanFlower::class,
self::BROWN_MUSHROOM => BrownMushroom::class,
self::RED_MUSHROOM => RedMushroom::class,
self::GOLD_BLOCK => Gold::class,
self::IRON_BLOCK => Iron::class,
self::DOUBLE_SLAB => DoubleSlab::class,
self::SLAB => Slab::class,
self::BRICKS_BLOCK => Bricks::class,
self::TNT => TNT::class,
self::BOOKSHELF => Bookshelf::class,
self::MOSS_STONE => MossStone::class,
self::OBSIDIAN => Obsidian::class,
self::TORCH => Torch::class,
self::FIRE => Fire::class,
self::MONSTER_SPAWNER => MonsterSpawner::class,
self::WOOD_STAIRS => WoodStairs::class,
self::CHEST => Chest::class,
self::DIAMOND_ORE => new DiamondOre(),
self::DIAMOND_BLOCK => new Diamond(),
self::WORKBENCH => new Workbench(),
self::WHEAT_BLOCK => new Wheat(),
self::FARMLAND => new Farmland(),
self::FURNACE => new Furnace(),
self::BURNING_FURNACE => new BurningFurnace(),
self::SIGN_POST => new SignPost(),
self::WOOD_DOOR_BLOCK => new WoodDoor(),
self::LADDER => new Ladder(),
self::DIAMOND_ORE => DiamondOre::class,
self::DIAMOND_BLOCK => Diamond::class,
self::WORKBENCH => Workbench::class,
self::WHEAT_BLOCK => Wheat::class,
self::FARMLAND => Farmland::class,
self::FURNACE => Furnace::class,
self::BURNING_FURNACE => BurningFurnace::class,
self::SIGN_POST => SignPost::class,
self::WOOD_DOOR_BLOCK => WoodDoor::class,
self::LADDER => Ladder::class,
self::COBBLESTONE_STAIRS => new CobblestoneStairs(),
self::WALL_SIGN => new WallSign(),
self::COBBLESTONE_STAIRS => CobblestoneStairs::class,
self::WALL_SIGN => WallSign::class,
self::IRON_DOOR_BLOCK => new IronDoor(),
self::REDSTONE_ORE => new RedstoneOre(),
self::GLOWING_REDSTONE_ORE => new GlowingRedstoneOre(),
self::IRON_DOOR_BLOCK => IronDoor::class,
self::REDSTONE_ORE => RedstoneOre::class,
self::GLOWING_REDSTONE_ORE => GlowingRedstoneOre::class,
self::SNOW_LAYER => new SnowLayer(),
self::ICE => new Ice(),
self::SNOW_BLOCK => new Snow(),
self::CACTUS => new Cactus(),
self::CLAY_BLOCK => new Clay(),
self::SUGARCANE_BLOCK => new Sugarcane(),
self::SNOW_LAYER => SnowLayer::class,
self::ICE => Ice::class,
self::SNOW_BLOCK => Snow::class,
self::CACTUS => Cactus::class,
self::CLAY_BLOCK => Clay::class,
self::SUGARCANE_BLOCK => Sugarcane::class,
self::FENCE => new Fence(),
self::PUMPKIN => new Pumpkin(),
self::NETHERRACK => new Netherrack(),
self::SOUL_SAND => new SoulSand(),
self::GLOWSTONE_BLOCK => new Glowstone(),
self::FENCE => Fence::class,
self::PUMPKIN => Pumpkin::class,
self::NETHERRACK => Netherrack::class,
self::SOUL_SAND => SoulSand::class,
self::GLOWSTONE_BLOCK => Glowstone::class,
self::LIT_PUMPKIN => new LitPumpkin(),
self::CAKE_BLOCK => new Cake(),
self::LIT_PUMPKIN => LitPumpkin::class,
self::CAKE_BLOCK => Cake::class,
self::TRAPDOOR => new Trapdoor(),
self::TRAPDOOR => Trapdoor::class,
self::STONE_BRICKS => new StoneBricks(),
self::STONE_BRICKS => StoneBricks::class,
self::IRON_BARS => new IronBars(),
self::GLASS_PANE => new GlassPane(),
self::MELON_BLOCK => new Melon(),
self::PUMPKIN_STEM => new PumpkinStem(),
self::MELON_STEM => new MelonStem(),
self::IRON_BARS => IronBars::class,
self::GLASS_PANE => GlassPane::class,
self::MELON_BLOCK => Melon::class,
self::PUMPKIN_STEM => PumpkinStem::class,
self::MELON_STEM => MelonStem::class,
self::FENCE_GATE => new FenceGate(),
self::BRICK_STAIRS => new BrickStairs(),
self::STONE_BRICK_STAIRS => new StoneBrickStairs(),
self::FENCE_GATE => FenceGate::class,
self::BRICK_STAIRS => BrickStairs::class,
self::STONE_BRICK_STAIRS => StoneBrickStairs::class,
self::MYCELIUM => new Mycelium(),
self::NETHER_BRICKS => new NetherBrick(),
self::MYCELIUM => Mycelium::class,
self::NETHER_BRICKS => NetherBrick::class,
self::NETHER_BRICKS_STAIRS => new NetherBrickStairs(),
self::NETHER_BRICKS_STAIRS => NetherBrickStairs::class,
self::END_PORTAL => new EndPortal(),
self::END_STONE => new EndStone(),
self::SANDSTONE_STAIRS => new SandstoneStairs(),
self::EMERALD_ORE => new EmeraldOre(),
self::END_PORTAL => EndPortal::class,
self::END_STONE => EndStone::class,
self::SANDSTONE_STAIRS => SandstoneStairs::class,
self::EMERALD_ORE => EmeraldOre::class,
self::EMERALD_BLOCK => new Emerald(),
self::SPRUCE_WOOD_STAIRS => new SpruceWoodStairs(),
self::BIRCH_WOOD_STAIRS => new BirchWoodStairs(),
self::JUNGLE_WOOD_STAIRS => new JungleWoodStairs(),
self::STONE_WALL => new StoneWall(),
self::EMERALD_BLOCK => Emerald::class,
self::SPRUCE_WOOD_STAIRS => SpruceWoodStairs::class,
self::BIRCH_WOOD_STAIRS => BirchWoodStairs::class,
self::JUNGLE_WOOD_STAIRS => JungleWoodStairs::class,
self::STONE_WALL => StoneWall::class,
self::CARROT_BLOCK => new Carrot(),
self::POTATO_BLOCK => new Potato(),
self::CARROT_BLOCK => Carrot::class,
self::POTATO_BLOCK => Potato::class,
self::QUARTZ_BLOCK => new Quartz(),
self::QUARTZ_STAIRS => new QuartzStairs(),
self::DOUBLE_WOOD_SLAB => new DoubleWoodSlab(),
self::WOOD_SLAB => new WoodSlab(),
self::STAINED_CLAY => new StainedClay(),
self::QUARTZ_BLOCK => Quartz::class,
self::QUARTZ_STAIRS => QuartzStairs::class,
self::DOUBLE_WOOD_SLAB => DoubleWoodSlab::class,
self::WOOD_SLAB => WoodSlab::class,
self::STAINED_CLAY => StainedClay::class,
self::LEAVES2 => new Leaves2(),
self::WOOD2 => new Wood2(),
self::ACACIA_WOOD_STAIRS => new AcaciaWoodStairs(),
self::DARK_OAK_WOOD_STAIRS => new DarkOakWoodStairs(),
self::LEAVES2 => Leaves2::class,
self::WOOD2 => Wood2::class,
self::ACACIA_WOOD_STAIRS => AcaciaWoodStairs::class,
self::DARK_OAK_WOOD_STAIRS => DarkOakWoodStairs::class,
self::HAY_BALE => new HayBale(),
self::CARPET => new Carpet(),
self::HARDENED_CLAY => new HardenedClay(),
self::COAL_BLOCK => new Coal(),
self::HAY_BALE => HayBale::class,
self::CARPET => Carpet::class,
self::HARDENED_CLAY => HardenedClay::class,
self::COAL_BLOCK => Coal::class,
self::PODZOL => new Podzol(),
self::BEETROOT_BLOCK => new Beetroot(),
self::STONECUTTER => new Stonecutter(),
self::GLOWING_OBSIDIAN => new GlowingObsidian(),
self::NETHER_REACTOR => new NetherReactor(),
);
self::PODZOL => Podzol::class,
self::BEETROOT_BLOCK => Beetroot::class,
self::STONECUTTER => Stonecutter::class,
self::GLOWING_OBSIDIAN => GlowingObsidian::class,
self::NETHER_REACTOR => NetherReactor::class,
];
}
}
@ -676,11 +679,12 @@ abstract class Block extends Position implements Metadatable{
*/
public static function get($id, $meta = 0, Position $pos = null){
if(isset(self::$list[$id])){
$block = clone self::$list[$id];
$block->setDamage($meta);
$block = self::$list[$id];
$block = new $block($meta);
}else{
$block = new Generic($id, $meta);
}
if($pos instanceof Position){
$block->position($pos);
}
@ -697,8 +701,6 @@ abstract class Block extends Position implements Metadatable{
$this->id = (int) $id;
$this->meta = (int) $meta;
$this->name = $name;
$this->breakTime = 0.20;
$this->hardness = 10;
}
/**
@ -760,7 +762,7 @@ abstract class Block extends Position implements Metadatable{
return [];
}else{
return [
array($this->id, $this->meta, 1),
[$this->id, $this->meta, 1],
];
}
}
@ -824,13 +826,20 @@ abstract class Block extends Position implements Metadatable{
* @param AxisAlignedBB $bb
* @param Block[] $list
*/
public function collidesWithBB(AxisAlignedBB $bb, &$list = array()){
public function collidesWithBB(AxisAlignedBB $bb, &$list = []){
$bb2 = $this->getBoundingBox();
if($bb2->intersectsWith($bb)){
if($bb2 !== null and $bb2->intersectsWith($bb)){
$list[] = $bb2;
}
}
/**
* @param Entity $entity
*/
public function onEntityCollide(Entity $entity){
}
/**
* @return AxisAlignedBB
*/
@ -845,6 +854,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,11 +47,16 @@ 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;
}
return false;
}
public function getBoundingBox(){
return null;
}
}

View File

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

View File

@ -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

@ -32,10 +32,15 @@ class Carrot extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -46,7 +51,7 @@ 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->getLevel()->setBlock($this, $this, true);
$item->count--;
return true;
@ -68,7 +73,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;
}
@ -83,9 +88,9 @@ class Carrot extends Flowable{
public function getDrops(Item $item){
$drops = [];
if($this->meta >= 0x07){
$drops[] = array(Item::CARROT, 0, mt_rand(1, 4));
$drops[] = [Item::CARROT, 0, mt_rand(1, 4)];
}else{
$drops[] = array(Item::CARROT, 0, 1);
$drops[] = [Item::CARROT, 0, 1];
}
return $drops;

View File

@ -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,14 +80,14 @@ 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);
@ -109,13 +121,13 @@ class Chest extends Transparent{
if($t instanceof TileChest){
$chest = $t;
}else{
$nbt = new Compound(false, array(
$nbt = new Compound(false, [
new Enum("Items", []),
new String("id", Tile::CHEST),
new Int("x", $this->x),
new Int("y", $this->y),
new Int("z", $this->z)
));
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$chest = new TileChest($this->getLevel()->getChunkAt($this->x >> 4, $this->z >> 4), $nbt);
}
@ -131,15 +143,15 @@ class Chest extends Transparent{
}
public function getDrops(Item $item){
$drops = array(
array($this->id, 0, 1),
);
$drops = [
[$this->id, 0, 1],
];
$t = $this->getLevel()->getTile($this);
if($t instanceof TileChest){
for($s = 0; $s < $t->getRealInventory()->getSize(); ++$s){
$slot = $t->getRealInventory()->getItem($s);
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$drops[] = array($slot->getID(), $slot->getDamage(), $slot->getCount());
$drops[] = [$slot->getID(), $slot->getDamage(), $slot->getCount()];
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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

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

View File

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

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

View File

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

View File

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

View File

@ -25,16 +25,21 @@ use pocketmine\item\Item;
use pocketmine\Player;
class Dirt extends Solid{
public $isActivable = true;
protected $hardness = 2.5;
protected $id = self::DIRT;
protected $meta = 0;
protected $name = "Dirt";
public function __construct(){
parent::__construct(self::DIRT, 0, "Dirt");
$this->isActivable = true;
$this->hardness = 2.5;
}
public function onActivate(Item $item, Player $player = null){
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,11 +21,22 @@
namespace pocketmine\block;
use pocketmine\item\Item;
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,17 +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{
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
$this->hasPhysics = true;
}
public $hasPhysics = true;
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$ret = $this->getLevel()->setBlock($this, $this, true, false, true);
$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()->getChunkAt($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){
@ -33,6 +36,19 @@ class Fire extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
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 [];
}
@ -45,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

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

View File

@ -27,17 +27,8 @@ use pocketmine\Player;
class Generic extends Block{
/**
* @param int $id
* @param int $meta
* @param string $name
*/
public function __construct($id, $meta = 0, $name = "Unknown"){
parent::__construct($id, $meta, $name);
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
return $this->getLevel()->setBlock($this, $this, true, false, true);
return $this->getLevel()->setBlock($this, $this, true, true);
}
public function isBreakable(Item $item){
@ -45,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,17 +22,22 @@
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\math\Vector3;
use pocketmine\level\Position;
use pocketmine\Player;
use pocketmine\utils\Random;
class Grass extends Solid{
public $isActivable = true;
protected $hardness = 3;
protected $id = self::GRASS;
protected $meta = 0;
protected $name = "Grass";
public function __construct(){
parent::__construct(self::GRASS, 0, "Grass");
$this->isActivable = true;
$this->hardness = 3;
}
public function getDrops(Item $item){
@ -49,7 +54,7 @@ class Grass extends Solid{
$z = mt_rand($this->z - 1, $this->z + 1);
$block = $this->getLevel()->getBlockIdAt($x, $y, $z);
if($block === Block::DIRT){
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
$block = Block::get($block, $this->getLevel()->getBlockDataAt($x, $y, $z), new Position($x, $y, $z, $this->getLevel()));
if($block->getSide(1) instanceof Transparent){
$this->getLevel()->setBlock($block, new Grass());
}
@ -60,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,17 +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;
}
@ -65,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){
@ -33,8 +35,22 @@ class Lava extends Liquid{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function onEntityCollide(Entity $entity){
$entity->setOnFire(15);
$ev = new EntityDamageEvent($entity, EntityDamageEvent::CAUSE_LAVA, 4);
Server::getInstance()->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$entity->attack($ev->getFinalDamage(), $ev);
}
$entity->attack(4, EntityDamageEvent::CAUSE_LAVA);
}
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);
$this->getLevel()->scheduleUpdate(clone $this, 40);
return $ret;

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

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

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

@ -32,10 +32,15 @@ class MelonStem extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -55,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{
@ -68,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);
}
}
}
@ -82,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--;
}
@ -94,8 +99,8 @@ class MelonStem extends Flowable{
}
public function getDrops(Item $item){
return array(
array(Item::MELON_SEEDS, 0, mt_rand(0, 2)),
);
return [
[Item::MELON_SEEDS, 0, mt_rand(0, 2)],
];
}
}

View File

@ -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

@ -2,11 +2,11 @@
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@ -22,6 +22,8 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\level\Position;
class Mycelium extends Solid{
public function __construct(){
@ -29,25 +31,25 @@ class Mycelium extends Solid{
$this->hardness = 2.5;
}
public function getDrops(Item $item){
return [
[Item::DIRT, 0, 1],
];
}
public function getDrops(Item $item){
return [
[Item::DIRT, 0, 1],
];
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_RANDOM){
//TODO: light levels
$x = mt_rand($this->x - 1, $this->x + 1);
$y = mt_rand($this->y - 2, $this->y + 2);
$z = mt_rand($this->z - 1, $this->z + 1);
$block = $this->getLevel()->getBlockIdAt($x, $y, $z);
if($block === Block::DIRT){
$block = $this->getLevel()->getBlock(new Vector3($x, $y, $z));
if($block->getSide(1) instanceof Transparent){
$this->getLevel()->setBlock($block, new Mycelium());
}
}
}
}
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_RANDOM){
//TODO: light levels
$x = mt_rand($this->x - 1, $this->x + 1);
$y = mt_rand($this->y - 2, $this->y + 2);
$z = mt_rand($this->z - 1, $this->z + 1);
$block = $this->getLevel()->getBlockIdAt($x, $y, $z);
if($block === Block::DIRT){
$block = Block::get($block, $this->getLevel()->getBlockDataAt($x, $y, $z), new Position($x, $y, $z, $this->getLevel()));
if($block->getSide(1) instanceof Transparent){
$this->getLevel()->setBlock($block, new Mycelium());
}
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -21,8 +21,6 @@
namespace pocketmine\block;
use pocketmine\item\Item;
class Podzol extends Solid{
public function __construct(){
parent::__construct(self::PODZOL, 0, "Podzol");

View File

@ -32,10 +32,15 @@ class Potato extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -46,7 +51,7 @@ 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->getLevel()->setBlock($this, $this, true);
if(($player->gamemode & 0x01) === 0){
$item->count--;
}
@ -69,7 +74,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;
}
@ -84,9 +89,9 @@ class Potato extends Flowable{
public function getDrops(Item $item){
$drops = [];
if($this->meta >= 0x07){
$drops[] = array(Item::POTATO, 0, mt_rand(1, 4));
$drops[] = [Item::POTATO, 0, mt_rand(1, 4)];
}else{
$drops[] = array(Item::POTATO, 0, 1);
$drops[] = [Item::POTATO, 0, 1];
}
return $drops;

View File

@ -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

@ -32,10 +32,15 @@ class PumpkinStem extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -56,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{
@ -69,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);
}
}
}
@ -83,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--;
}
@ -95,8 +100,8 @@ class PumpkinStem extends Flowable{
}
public function getDrops(Item $item){
return array(
array(Item::PUMPKIN_SEEDS, 0, mt_rand(0, 2)),
);
return [
[Item::PUMPKIN_SEEDS, 0, mt_rand(0, 2)],
];
}
}

View File

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

View File

@ -31,6 +31,11 @@ class RedMushroom extends Flowable{
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function onUpdate($type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(0)->isTransparent === true){ //Replace with common break method
@ -48,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,22 +37,27 @@ class Sapling extends Flowable{
public function __construct($meta = Sapling::OAK){
parent::__construct(self::SAPLING, $meta, "Sapling");
$this->isActivable = true;
$names = array(
$names = [
0 => "Oak Sapling",
1 => "Spruce Sapling",
2 => "Birch Sapling",
3 => "Jungle Sapling",
4 => "Acacia Sapling",
5 => "Dark Oak Sapling",
);
];
$this->name = $names[$this->meta & 0x07];
$this->hardness = 0;
}
public function getBoundingBox(){
return null;
}
public function place(Item $item, Block $block, Block $target, $face, $fx, $fy, $fz, Player $player = null){
$down = $this->getSide(0);
if($down->getID() === self::GRASS or $down->getID() === self::DIRT or $down->getID() === self::FARMLAND){
$this->getLevel()->setBlock($block, $this, true, false, true);
$this->getLevel()->setBlock($block, $this, true, true);
return true;
}
@ -89,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;
}
@ -102,8 +107,8 @@ class Sapling extends Flowable{
}
public function getDrops(Item $item){
return array(
array($this->id, $this->meta & 0x07, 1),
);
return [
[$this->id, $this->meta & 0x07, 1],
];
}
}

View File

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

View File

@ -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,11 +85,11 @@ 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;
}
@ -74,7 +97,7 @@ class Slab extends Transparent{
}elseif(!($player instanceof Player)){
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;
}
@ -91,7 +114,7 @@ class Slab extends Transparent{
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 +139,9 @@ class Slab extends Transparent{
public function getDrops(Item $item){
if($item->isPickaxe() >= 1){
return array(
array($this->id, $this->meta & 0x07, 1),
);
return [
[$this->id, $this->meta & 0x07, 1],
];
}else{
return [];
}

View File

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

View File

@ -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,6 +22,7 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\Player;
class Stair extends Transparent{
@ -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,6 +21,9 @@
namespace pocketmine\block;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\Server;
use pocketmine\entity\Entity;
class StillLava extends Liquid{
public function __construct($meta = 0){
@ -28,4 +31,18 @@ class StillLava extends Liquid{
$this->hardness = 500;
}
public function getBoundingBox(){
return null;
}
public function onEntityCollide(Entity $entity){
$entity->setOnFire(15);
$ev = new EntityDamageEvent($entity, EntityDamageEvent::CAUSE_LAVA, 4);
Server::getInstance()->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$entity->attack($ev->getFinalDamage(), $ev);
}
$entity->attack(4, EntityDamageEvent::CAUSE_LAVA);
}
}

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

@ -32,8 +32,11 @@ class Stone extends Solid{
const ANDESITE = 5;
const POLISHED_ANDESITE = 6;
protected $hardness = 30;
protected $id = self::STONE;
public function __construct($meta = 0){
parent::__construct(self::STONE, $meta, "Stone");
$this->meta = $meta;
$names = [
self::NORMAL => "Stone",
self::GRANITE => "Granite",
@ -44,7 +47,6 @@ class Stone extends Solid{
self::POLISHED_ANDESITE => "Polished Andesite",
];
$this->name = $names[$this->meta & 0x07];
$this->hardness = 30;
}
public function getBreakTime(Item $item){
@ -66,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 [];
}

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