Compare commits

...

267 Commits

Author SHA1 Message Date
07bf1c9e22 Bump API version for release 2018-02-04 18:06:02 +00:00
b659a3d39f Server: more shutdown debug 2018-02-04 10:14:35 +00:00
68b30108be CrashDump: fix mis-reporting Composer dependency exceptions as plugin crashes
this is still not foolproof but whatever.
2018-02-03 19:27:59 +00:00
f223fb2876 Use realpath() to determine correct file path case for DATA and PLUGIN_PATH
fixes issues where cleanPath() doesn't remove these paths from crash traces
2018-02-03 19:21:13 +00:00
8bb785b7af Update pthreads for Travis 2018-02-03 14:17:42 +00:00
806a2005d7 added missing dependency check for OpenSSL
this is managed by Composer now so I didn't think to check it.
2018-02-03 01:03:59 +00:00
c794ced0ad fix dependencies order 2018-02-03 01:03:08 +00:00
f993358c5f fixed extremely stupid bug with player spawns
This was causing new players to inexplicably spawn in the wrong place when joining a world for the first time which had a different level name than folder name. With LevelDB worlds, this caused them to spawn wayyyy up at y=32767 for no good reason.
2018-02-02 16:00:28 +00:00
1c12be6bf2 README: Remove IRC
these channels have been dead for years.
2018-02-02 09:31:13 +00:00
a1d9b8486e README: Be more clear about "getting latest phar"
We don't want people to be using latest development builds, but that's the first thing people see when visiting Jenkins. We want them using releases instead.
2018-02-02 09:28:22 +00:00
9397356ce4 Server: fix crash when specifying settings.async-workers on the command-line 2018-02-01 17:58:49 +00:00
e56e363dcc DataPacket: rename split-screen bytes 2018-01-31 12:07:26 +00:00
18b287c3ea AsyncTask: Remove cleanObject() and calls to it
This is no longer needed. Doing worker GC (via collect()) frees the allocated memory anyway, so this function is now redundant.
2018-01-30 16:45:49 +00:00
9014eb72e9 TeleportCommand: Fixed the bug fix again
This all comes from a shitty bugfix by @PEMapModder. Should be applied globally really, but it wasn't - and not properly tested either :P
2018-01-30 15:08:11 +00:00
82948726ed Beware threads/workers might not inherit \pocketmine\PATH
if the inherit flags don't include PTHREADS_INHERIT_CONSTANTS, this code would fail. Store the Composer autoloader path in advance instead.
2018-01-30 14:50:19 +00:00
c601816586 Terminal::hasFormattingCodes() workaround for STDOUT not being defined
#1979

This isn't a full solution because formatting codes are still not applied correctly if the calling thread doesn't inherit classes.
2018-01-30 10:54:04 +00:00
d2d1df0447 MainLogger: Remove redundant condition
these are always ThreadedLoggerAttachments anyway, this code doesn't make sense.
2018-01-29 12:24:00 +00:00
f9b1afe4cf Fixed race condition causing exception log messages to sometimes not get written to disk when kill() is used
Synchronize with the logger thread when logging an exception or killing. This forces the main thread to wait for disk write to complete when logging exceptions or killing the process.
2018-01-29 12:04:23 +00:00
033cb8bd63 oops, wrong namespace 2018-01-28 13:08:11 +00:00
0ed9fcb641 Restrict VerifyLoginTask exception handling to known exceptions
everything else should produce a nice big stack trace for debugging purposes, because everything else is probably bugs

This fixes random exception error messages getting relayed to the client when a user does stupid things like editing the source code without knowing what they are doing.
2018-01-28 13:07:09 +00:00
efac23d4af Updated to new RakLib version 2018-01-27 19:10:55 +00:00
48dc1c38f7 Generator: fixed misuse of InvalidArgumentCountException 2018-01-27 12:46:09 +00:00
ffb3e2b47a Player: Fixed logical nonsense in removeWindow()
The only time this is set anyway is obviously if the ID is non-null.
2018-01-27 11:02:03 +00:00
ef816c0a52 Player: Fixed window ID of closing inventory always being -1
reported by @Muqsit, thank you sir
2018-01-27 11:00:08 +00:00
3e35bc38e2 Inventory: Fixed crash when breaking right half of a double chest while open 2018-01-27 10:57:04 +00:00
de0741f727 Item: remove unused imports 2018-01-26 17:12:00 -05:00
6fd4b9f1e2 Entity: Cater for old data with CustomNameVisible as a StringTag
This was a bug in older versions, fixed by 890f72dbf2. However since ALPHA10 this has been moved to the new, strict-ified CompoundTag API, which shits its pants when it encounters a tag of the wrong type.

Closes jojoe77777/Slapper#119
2018-01-26 20:01:04 +00:00
6c8a1a5b80 Item: Remove redundant Level parameter from onActivate()
there are three other sources this could be gotten from, an arbitrary level doesn't make sense.
2018-01-25 10:15:36 +00:00
3842ee15cf Item: Removed now-obsolete Cake class
>> As of 1.2, cake has a max stack size of 64, making this class redundant as its only purpose was to declare a stack size of 1.
2018-01-25 10:09:09 +00:00
6c71b443e8 Fixed armor not dropping (#1962) 2018-01-24 20:01:32 +00:00
4a4900e5e7 Revert bad duct-tape fix that broke lots of other things
Revert "Fixed players getting full health on rejoin after quitting on death"

This reverts commit 1d4bafb6ff.
2018-01-24 19:21:32 +00:00
26d4169fea EntityShootBowEvent: Remove unnecessary kill() 2018-01-24 19:17:08 +00:00
7d88a8b315 Player: Remove useless assignments from constructor 2018-01-24 18:22:23 +00:00
41592a04b7 InventoryTransactionPacket: Update some field names 2018-01-24 13:50:30 +00:00
1d4bafb6ff Fixed players getting full health on rejoin after quitting on death
This makes #1567 less exploitable. Now, players who attempt to exploit this bug will get stuck - they won't be able to move or do anything. Not ideal, because they won't be able to respawn either - but it's better than nothing.
2018-01-24 12:27:10 +00:00
28996f561f Player: Added a hack for knockback being messed up
This needs to be updated server side and isn't because of the way player movement is currently handled. Fixing this properly will require a lot more work than this.
2018-01-24 11:56:32 +00:00
0658c0851b Entity: Remove some unused properties 2018-01-24 11:37:01 +00:00
0df2064802 Implement armor damage protection enchantments (#1839) 2018-01-24 10:13:24 +00:00
6543d96910 Inventory: Split up armor and player inventory (#1957)
* Inventory: Split up PlayerInventory and armour handling
* Fixed other players don't see armour changes. This bug also exists on master.
2018-01-23 20:01:26 +00:00
0bf5ab76fb Remove WeakRef leftovers 2018-01-23 19:04:37 +00:00
8e1394bf53 MemoryManager: Use get_declared_classes() to build lists of static properties
This makes memory dumping independent from the autoloader implementation, and fixes #1958.
2018-01-23 18:23:53 +00:00
6ddbdc9dc1 Fixed worker memory dump crash
$GLOBALS does not exist at all on threads :(
2018-01-23 17:21:24 +00:00
2a8be527d7 Remove redundant paths from BaseClassLoader
Everything under src is now handled by the Composer autoloader, and SPL doesn't exist anymore (it's a Composer library now).
2018-01-23 17:03:04 +00:00
aca1422fca Updated pthreads version for Travis 2018-01-23 16:49:32 +00:00
b0d0932ed9 DoubleChestInventory: Fixed items getting rearranged in single chests when creating a double chest
I fixed this elsewhere more than 18 months ago, why is this still here?
2018-01-23 15:50:13 +00:00
fd5557861b Changed how login verification is handled, add more useful error messages
closes #1955
2018-01-28 14:13:59 +00:00
1de7c5b114 Inventory: Added includeEmpty parameter to getContents() 2018-01-22 22:33:57 +00:00
2fb580db26 Inventory: Removed need for Inventory to have an InventoryHolder
Inventory holders are now freed from BaseInventory. They are now declared by subclasses by convention, but are not required in most cases.

Ideally, this would be followed by the removal of the need for inventories to know their holders at all. They should just be simple containers of items.

This fixes #1560 by removing FakeBlockMenu.
2018-01-22 19:44:52 +00:00
e5ca22a9a6 Player: Simplified implementation of windows => window ID map
it is not necessary to reference the actual objects here. Doing so makes the implementation more confusing. Hashes are sufficient.
2018-01-22 18:58:19 +00:00
69ddaacc28 Inventory: Add a $send parameter to clearAll() 2018-01-22 18:39:39 +00:00
897a31e608 Player: Moved logic of setUsingItem()
plugins might be using this method, or the item may have been dropped involuntarily due to server-side logic. Therefore it should be handled when the transaction is received and not when the item is dropped into the world.
2018-01-22 18:36:48 +00:00
4943ff9dfc Not sure how this got missed :< 2018-01-21 19:36:42 +00:00
e36b38939c Lever: fix placement 2018-01-21 17:53:41 +00:00
ecb3f9aeac Level: Allow broadcastLevelEvent() to accept a null position to broadcast to everyone in the Level 2018-01-21 17:41:00 +00:00
f0696f77ef Level: Added global packet broadcast mechanism 2018-01-21 17:40:31 +00:00
6813838754 EntityDamageEvent: Remove redundant TODO
Armor does absorb lightning damage by default.
2018-01-21 17:40:03 +00:00
65fe19ca71 Entity: Fixed logic error in getBlocksAround() which caused yet another firebug
Try setting a fire at z = -204, then stand on the edge between -205 and -206.

The coordinates that a BB's corners are encapsulated in are always the floor()ed coordinates

If you stand at -205.0, your BB min is -205.3 and your BB max is -204.7, which then incorrectly tells you that the BB intersects with block -204
because ceil(-204.7) == -204
when you actually are only intersecting with -205 and -206
this is as bad as using (int) to floor integers :kms:
2018-01-21 15:43:03 +00:00
a4f5cab12d Entity: Added getDataPropertyManager() 2018-01-20 20:07:11 +00:00
29e06e30b2 Fix projectiles throwing errors on launching, fix #1942 (#1943)
* Fix Projectile::setOwningEntity() on null error
2018-01-20 18:07:53 +00:00
3939e2d9dd NetworkBinaryStream: add some typehints 2018-01-20 11:05:41 +00:00
2579438b84 NetworkBinaryStream: Use nullable typehint for putVector3Nullable() instead of default value
the parameter is not optional
2018-01-20 11:01:16 +00:00
95d42b9907 Network: Remove legacy Vector3 primitive encode/decode methods 2018-01-20 10:58:39 +00:00
2eb6e075ae Refactored entity metadata handling into its own class, with type-safe methods (#1876)
This includes several other changes, including:
- SLOT data properties now accept items directly
- POS data properties now accept floored Vector3s (in future this will be block positions) or null for 0,0,0
- VECTOR3F data properties now accept Vector3s or null for 0,0,0
2018-01-20 10:52:14 +00:00
8f928915d9 Merge PR #1936: Vector3:: setComponents() documentation fix
Vector3::setComponents() and override changes/removal
2018-01-19 08:12:44 +00:00
3af8cf48b2 Removed setComponents() override in Position 2018-01-18 19:03:53 -05:00
21c03670b6 PhpDoc fix for my sanity 2018-01-18 18:04:54 -05:00
0c868b16b6 Network: Added config to pocketmine.yml to allow changing max MTU size
This might be useful for people with older routers where the connection MTU is actually lower than the router allows.
2018-01-18 18:15:14 +00:00
1e67360048 SpawnEgg: Remove redundant isSurvival() check 2018-01-18 17:04:25 +00:00
3520dafd29 Entity: Make fall distance explicit float to shut a PhpStorm bug up 2018-01-18 16:52:17 +00:00
857b63ba8f Entity: Added recalculateBoundingBox() 2018-01-18 16:35:38 +00:00
9551e5b8e5 Durable: Allow subclasses to override behaviour when the item breaks 2018-01-18 14:37:22 +00:00
c7f15a556d Durable: Don't allow damage to exceed max damage 2018-01-18 14:34:50 +00:00
efca9f0450 Item: Moved getMaxDurability() to Durable class only, and make it abstract
It's only now used in the Durable class, so it does not make sense to keep it in Item anymore. This is a leftover from the days where Durable did not exist.
2018-01-18 14:16:30 +00:00
d728154e87 Level: Fixed entities getting deleted when switching levels
So this came from a bugfix (795d6c8ddf) which fixed a memory leak related to entities getting kill()ed on chunk unload.
HOWEVER, me2016 did NOT realize that this code is actually entirely pointless and causes unexpected behaviour.

removeEntity() is used in 2 places in the core code:
1. in Entity->close() (so close() doesn't need to be called again, obviously)
2. in Entity->switchLevel() (which then causes the entirely unexpected behaviour of close()ing the entity on level change.

Conclusion: This code is pointless. This fixes the bugfix.
2018-01-17 11:30:59 +00:00
2e1a167bed Arrow class: No need to import Item class with other name (#1932) 2018-01-17 10:59:50 +00:00
6f6e3aaa21 Fixed projectiles collding with spectator players
closes #1857
2018-01-17 10:57:04 +00:00
9c65a2b890 Furnace: Fixed lit furnaces dropping the wrong item
closes #1915
2018-01-17 10:24:01 +00:00
beb5bf6dda Add API methods: Entity::isInvisible(), Entity::setInvisible() (#1930)
* Make use of the API function in Effect class
2018-01-17 09:56:59 +00:00
7a5e5773b7 Updated RakLib dependency 2018-01-16 20:01:41 +00:00
f1b0a4f1de Not sure why we are still blaming @shoghicp for this :< 2018-01-15 11:17:01 +00:00
751345c736 Updated BinaryUtils dependency 2018-01-14 18:56:31 +00:00
e850f34d76 Fix TNT block not setting fuse NBT correctly (#1917) 2018-01-14 18:10:57 +00:00
8d7c65585c Enchantment: Implement Silk Touch (#1912) 2018-01-14 13:37:27 +00:00
96f6362117 Fixed glowing redstone ore giving itself when block-picked 2018-01-14 13:35:41 +00:00
66c768d453 PR template: Make clear that "tested" is not acceptable test information
[ci skip]
2018-01-14 11:44:29 +00:00
6fe7763db9 Contributing: require details of tests done
[ci skip]
2018-01-14 11:37:51 +00:00
fda97decaa Contributing: batch commit of changes
very hypocritical of me, I know...

[ci skip]
2018-01-14 11:35:04 +00:00
b3f44562e9 Contributing: updated example
[ci skip]
2018-01-14 11:04:46 +00:00
51350be190 CONTRIBUTING.md: fixed indentation
[ci skip]
2018-01-14 10:42:53 +00:00
7f4b5d282e Fixed plugin name validation
Invalid characters in plugin names are no longer stripped. They always result in a load error.

The behaviour of replacing spaces with underscores is not changed.
2018-01-14 18:28:19 +08:00
94feecd44b Enchantment: Implemented Unbreaking 2018-01-13 19:34:45 +00:00
45b02d92d4 Math: Added RayTraceResult, removed dependence on MovingObjectPosition
MOP doesn't make any sense anyway.

RayTraceResult is a container which represents the point at which a line hits a bounding box. No dependence on blocks or entities is wanted or needed.
MovingObjectPosition has API changes to allow it to wrap RayTraceResult, but nothing uses MOP anymore anyway.

This would allow modularisation of the pocketmine\\math namespace.
2018-01-12 14:28:41 +00:00
fe4b5498e6 Level: Fixed 2D block cache not getting counted correctly
Fixes #1903
Closes #1906, which, while a pretty solution, is very inefficient (see PR discussion). This is an optimization of microscopic proportions, but the point still stands.
2018-01-12 11:02:43 +00:00
98b36fd73e Enchantment: Implemented Efficiency
This is only needed server-side for block-break animation times.
2018-01-11 20:13:57 +00:00
07c7048433 Enchantment: Converted item type bitflags to hex 2018-01-11 20:09:42 +00:00
f09cf92197 Enchantment: Updated item type flags 2018-01-11 20:08:50 +00:00
98eba11da5 Human: Use Item->getEnchantmentLevel() for Respiration check 2018-01-11 18:32:46 +00:00
a6c1e02847 Enchantment: Register Respiration enchantment
First working enchantment on master. Hooray for 3 years late.

This works out of the box (the code checking for this enchantment already exists in Human->doAirSupplyTick()).
2018-01-11 18:32:22 +00:00
b04cee12ea Item: Added API method getEnchantmentLevel() 2018-01-11 18:22:29 +00:00
c4966404bb Moved NBT to Composer library 2018-01-11 14:18:09 +00:00
579c508761 Move Binary and BinaryStream to Composer library 2018-01-11 13:19:59 +00:00
43959bccb1 Change Composer package vendor name to pocketmine instead of pmmp, update dependencies 2018-01-11 13:16:27 +00:00
e6bd12dc2f Consolidated MCPE network binary handling methods into one class, remove protocol-specific methods from BinaryStream
Remove MCPE-network specific stuff from BinaryStream, added NetworkBinaryStream
This removes dependencies of BinaryStream on core code, while providing some consolidation of network handling code.
2018-01-11 12:28:56 +00:00
7daca754b1 BinaryStream: Fixed wrong header being included
This is currently harmless, except for adding a redundant extra use
statement. However harmless it is though, it is still incorrect.
2018-01-11 12:26:50 +00:00
cb90e30bcf Entity: Fixed intersecting with blocks they aren't actually intersecting with...
at the expense of magma no longer working (which will need to be done better anyway).

This:
- reverts the +0.01 outset which hugely exacerbated the lava bug (fixes #1892)
- adds a 0.001 inset (PC-style) which prevents entities incorrectly intersecting with diagonally adjacent blocks at far-ish coordinates (lava at x=4000, z=4000 is a good way to test this).

PR #1880 does also solve this issue, but again at the expense of magma. Since the bugfix does not require a big bounding-box handling refactor, it has been separated out.
2018-01-11 11:10:36 +00:00
71d11c73f0 Math: Kill BlockIterator, added a VoxelRayTrace class with level-independent generator functions (#1885)
This is a rather larger commit than I'm happy with, but oh well.

This kills off the enormously overcomplicated BlockIterator and replaces it with a VoxelRayTrace class containing ray tracing generator functions. These functions are independent of any Level. They yield Vector3 objects with current ray trace positions to allow implementations to handle the intercepted blocks in their own ways.

Living->getLineOfSight() now uses VoxelRayTrace instead of BlockIterator.
2018-01-10 20:14:36 +00:00
24116ba846 Remove old pthreads v2 workarounds
This used to cause problems in earlier versions of pthreads if PTHREADS_INHERIT_CLASSES was not used. This is no longer a problem in pthreads v3, because pthreads v3 copies passed threaded object classes under the hood, so there is no need to manually include them anymore.

Additionally, the files in these paths don't exist anymore.
2018-01-10 10:59:58 +00:00
a0683dbb0f Chunk: Remove useless code in fastDeserialize() 2018-01-08 21:38:30 +00:00
b6811b643c .gitignore: Ignore all directories starting with bin
This might cause problems later on, but it's unlikely. Right now however, I am tired of my various PHP version directories showing up in git untracked files.
2018-01-08 11:17:29 +00:00
4d2549b50a PlayerInventory: Fixed $send parameter not working for setting armour slots 2018-01-06 16:24:41 +00:00
1fb3274f37 Server: Make start() private
This should not be exposed to plugin use.
2018-01-06 15:04:58 +00:00
6772a69c55 Server: Prevent construction of more than one server instance at a time
I have no idea when one might choose to do this, but it could cause extremely undesirable effects, so it should be prevented.
2018-01-06 14:58:51 +00:00
266a253c03 Remove dead imports 2018-01-05 19:48:04 +00:00
c62e1abf2f Kill the instabreak anti-cheat
This is annoying and it requires that the server must match this precisely to not cause bugs. Additionally, this code shits its pants when the client hits a spot of network lag.

This can be implemented easily as a plugin. There is no reason whatsoever for this to be in the core.
2018-01-05 19:43:51 +00:00
55f405f5c2 Player: Extend acceptable block-break distance by 1
Survival reach distance is 6, but that's only a measure of how far the player must reach to hit any part of the target block. Measured from the centre, this again provides a possible corner reach which is too far away from the centre of the block by sqrt(3) / 2 blocks.

Simple fix - allow an extra block's distance.
2018-01-05 19:36:02 +00:00
8fbd0e58f0 Level: Fixed possible crash with changed blocks handling
Since chunks are unloaded before changed blocks are processed, there is a small chance that a block might get changed in a chunk, and then get unloaded due to not being in use, before the updates are broadcasted.
This is unlikely to ever happen since chunks usually don't get unloaded unless they don't have loaders anyway, but it could happen (?) if a chunk is forcefully unloaded.
2018-01-05 13:46:21 +00:00
418d099a2e Merge PR #1561: Implement XP 2018-01-05 12:53:48 +00:00
9d2eb5e911 Human: Added some void typehints 2018-01-05 12:30:03 +00:00
b6c1124d50 Move XP drop amount to Human instead of Player 2018-01-05 12:09:24 +00:00
03fda936a8 Added XP level-up sounds and refactored XP gain sound handling 2018-01-05 11:58:54 +00:00
684fd46d09 Entity: Throw exception when trying to get save ID of non registered entity 2018-01-04 21:05:17 +00:00
90fc649441 Fixed bad PhpDoc leftovers from NBT streams refactor 2018-01-04 20:32:06 +00:00
0410df77aa Drop experience on death 2018-01-04 19:33:37 +00:00
0f30467f62 Added Level->dropExperience() and API for splitting XP into orb sizes 2018-01-04 19:32:54 +00:00
a84910f04c Implemented XP orbs 2018-01-04 19:28:19 +00:00
3ee225caec Human: Refactored XP API methods 2018-01-04 19:15:26 +00:00
f963dbd10d Level: Added getNearestEntity()
This may be used for AI in the future.
2018-01-04 19:10:43 +00:00
debfbf0d93 Math: Added solveQuadratic()
will be used in future for XP. This is extracted from the experience work branch.
2018-01-04 15:58:54 +00:00
5c37d298a6 Player: Changed canInteract() default max diff to sqrt(3) / 2
This is needed because players can break blocks that are outside of their field of view. A player can be inside a block and be able to break that block, while looking up, which places its centre (which is where the interact check is done from) actually behind the player's field of view. This causes anti-cheat to be triggered and makes it impossible to break blocks one is inside.

This commit changes the max negative diff to be half of the distance between a block's centre and its corners (M_SQRT_3 / 2).
2018-01-04 15:46:49 +00:00
3ca162f23f Revert "Player: Remove obsolete maxDiff parameter from canInteract()"
This reverts commit a5c3fbdd7a.
2018-01-04 15:33:23 +00:00
5f48433c95 Bucket: Added sounds for bucket fill/empty 2018-01-03 14:27:41 +00:00
33352638a9 Bucket: Fixed appearing empty when picking up still liquids
Buckets already affected by this bug will still appear empty until used. After that they'll work fine.
2018-01-03 14:22:53 +00:00
db52501462 Bucket: Fixed stack size handling for empty buckets
GOD this code is horrible
close #1472
2018-01-03 14:12:04 +00:00
3a0cbd1cd4 Block: Cleaned up double-block break handling, close #1862, close #1525
This now removes the need for recursing around for structures comprised of multiple blocks. Instead, override getAffectedBlocks() to return all blocks that need to be deleted when the current block is deleted, and make sure that only one half of the block drops something. When a player breaks one of the blocks, all the blocks affected by that block will also be destroyed, creating particles and sounds where appropriate.

This fixes creative drops for double plants and beds.
2018-01-03 13:01:05 +00:00
1bdb68b7da EnderChest: Remove dead onBreak() code (follow-up to previous commit) 2018-01-03 12:10:36 +00:00
6ce728169e Chest: Remove redundant unpairing code from onBreak()
This is already done in the Level.
2018-01-03 12:08:35 +00:00
06a3c7c478 Entity: Write attributes in AddEntityPacket 2018-01-03 11:30:22 +00:00
70982c145b Level: Clarified documentation for loadChunk() and changed misleading parameter name 2018-01-02 18:08:43 +00:00
417f2d8998 Level: Clarified documentation on getChunk() 2018-01-02 18:05:30 +00:00
7339c4ac2f Player: Fixed not being able to interact with blocks in adventure mode, close #1848
This allows other undesired behaviour like flint&steel, buckets to work in adventure mode when they shouldn't, but that's a bug for another time.
2018-01-02 16:26:59 +00:00
43a0ede9d2 Player: Fix floating-point errors when float Vector3s are given to sleepOn()
In the future this will change to block positions and the Vector3 issue will cease to be an issue.

Closes #1871
2018-01-02 16:09:58 +00:00
c747c7d025 Throw exceptions when entities/tiles are created on chunks that don't exist
These assertions don't make sense. Since the chunk field is used below in both cases, the chunk should **never** be null no matter what.
2018-01-02 13:12:54 +00:00
c9e2e8980f Fixed some places entities/players use their chunk without checking if it is valid
This may be invalid in some cases, such as:
- chunk is not loaded
- entity is not fully constructed
- entity is a Player who has not yet completed the login sequence.
2018-01-02 12:57:04 +00:00
9a956692de Fixed wasteful throwaway objects used for spawn positions 2018-01-02 12:21:11 +00:00
d30a6b60b7 .gitignore: Ignore crashdumps directory
How did this never become a problem before?!
2018-01-02 12:09:31 +00:00
41873bb115 Merge PR #1864: LevelProviders refactor 2018-01-02 11:47:11 +00:00
8064152777 LevelProvider: Add documentation for doGarbageCollection() and close() 2018-01-02 11:39:51 +00:00
872df446bd Level: Remove redundant duplicate condition in unloadChunk() 2018-01-02 11:16:20 +00:00
376a615634 thanks for the warning PhpStorm... not 2018-01-02 11:14:01 +00:00
c16c9efdf3 Chunk: Rename unload() to onUnload()
this more accurately describes what the function does.
2018-01-02 10:50:22 +00:00
c3cc6f9880 Chunk: Clean up unnecessary checks in unload() 2018-01-02 10:48:01 +00:00
1e139743b8 Level: Do level provider GC every 5 minutes from level tick
this should solve #1183, pending further testing.
2018-01-02 10:23:57 +00:00
bde0ba1100 Level: Set chunk coordinates in setChunk()
The level provider used to do this in LevelProvider->setChunk(), but it does not anymore.
2018-01-01 13:13:47 +00:00
50f273c041 Vector2: Fixed ceil() and floor() totally broken logic
"So if I Vector2->ceil()->ceil() my vector2 magically gets incrementing values..." @Sandertv 2018
2018-01-01 12:57:34 +00:00
db095f9705 Updated PreProcessor submodule 2018-01-01 12:54:18 +00:00
f580f27ec7 LevelProvider: Updated documentation 2018-01-01 11:59:22 +00:00
a46029c0f6 LevelProvider: Nuked the complicated mess out of level providers
Level providers are now cut back to just an interface to a world's data. They don't keep their own chunk registries or any stupid shit like that because the Level already does that.

This furthers the goal of being able to move level I/O off the main thread, and also drastically decreases the complication of implementing level providers.
2018-01-01 11:21:46 +00:00
1a615591e2 LevelProvider: Remove cyclic dependency between Level and LevelProvider
This will now allow LevelProviders to be constructed on threads.
2018-01-01 10:50:13 +00:00
d19683b7dd LevelProvider: Remove some dead methods 2017-12-31 18:35:23 +00:00
f17b3b2a3b LevelProvider: Refactor providers to drop lots of duplicated code 2017-12-31 18:35:23 +00:00
a0a2ea01bc LevelDB: Check for LEVELDB_ZLIB_RAW_COMPRESSION when checking for the extension's presence
We always want to validate that the leveldb provided supports the world format.
2017-12-31 17:49:02 +00:00
5132ab6cd9 LevelDB: Remove redundant folder creation in generate()
This is pointless because the call below - which is _also_ recursively creating directories - will create this directory anyway.
2017-12-31 17:46:07 +00:00
256bdf2581 McRegion: Use MainLogger::getLogger()
another one bites the dust
2017-12-31 16:06:08 +00:00
8a3f8b4706 LevelProvider: Remove redundant method requestChunkTask()
This removes one more dependency that LevelProvider has on Level.
2017-12-31 16:05:58 +00:00
7264ce43ae McRegion: Added method pathToRegion() 2017-12-31 14:25:17 +00:00
66e475cbb8 Region: Remove RegionLoader/McRegion cyclic dependency 2017-12-30 19:59:35 +00:00
1e896efff9 McRegion: Added an assert 2017-12-30 19:49:44 +00:00
4db7a7e57f Region: Change chunk offset calculation in regions to use bitmasks
I don't know why it wasn't done like this to start with. However this has not been tested yet, so this goes on a different branch for now to test.
2017-12-30 19:41:58 +00:00
54b23968e7 McRegion: Refactor some ambiguous variable names 2017-12-30 18:59:01 +00:00
bcb080e2b9 Level: Make sleepTicks private, don't write directly 2017-12-30 18:41:13 +00:00
e5c58f9b04 Player: Add typehint for maxDistance parameter of canInteract()
Not sure why this was missing :<
2017-12-30 17:43:12 +00:00
af7aef70db Implemented TextFormat::colorize() (#1837)
Implemented TextFormat::colorize()
See 4c46087ffc for the initial discussion
2017-12-30 16:51:04 +00:00
3ea72a0bf9 Merge PR #1775: NBT streams refactor 2017-12-30 15:53:47 +00:00
be02fbb352 NBT: Add typehints to PHP 7.2 standards 2017-12-30 15:07:50 +00:00
a67f7e3930 Add header includes and preprocessor checks 2017-12-30 14:56:29 +00:00
965c19375f NBT: Split up concerns of endianness and varint NBT into their own classes, separate stream handling from NBT class
The remaining methods, constants and fields in the NBT class now pertain to generic NBT functionality (except for the matchList()/matchTree() methods, but that's a job for another time). All NBT I/O specific logic has now been moved to NBTStream and its descendents.
2017-12-30 14:55:45 +00:00
63edcb8934 Updated PreProcessor submodule 2017-12-30 14:15:33 +00:00
e7a012d69a Player: Remove dead imports 2017-12-30 12:42:42 +00:00
99c55ac889 Plugin: Fixed return type documentation for getResource() 2017-12-30 12:40:50 +00:00
f14adf5827 Updated RakLib dependency 2017-12-28 12:51:16 +00:00
c64b9ad63a MovingObjectPosition: Use asVector3() instead of creating a new vector the hard way 2017-12-26 15:37:00 +00:00
dda71b06ae AxisAlignedBB: Use elseif in calculate*Offset()
It's impossible for both of these conditions to be met in the same call.
2017-12-26 14:31:42 +00:00
3c4dca7fdb ZippedResourcePack: Handle json decoding errors correctly
Previously this would crash if it failed to decode the JSON (https://forums.pmmp.io/threads/texture-pack-shows-errors-not-working.4880/)
2017-12-25 19:01:02 +00:00
ddbc5cf960 Player: Use fmod() instead of modulo operator for yaw/pitch
the modulo (%) operator only operates on integers. If it's used on floats, they are silently casted to ints, which results in loss of accuracy. Fractions of a degree might not seem important, but for ray-tracing purposes a fraction of a degree can make the difference between hit and miss.
2017-12-24 19:48:43 +00:00
1edf69892a Fixed chorus fruit teleporting players into the void in superflat worlds 2017-12-24 16:27:58 +00:00
f10c2a2df2 FlowerPot: Fix drops retaining damage
close #1844
2017-12-23 17:54:22 +00:00
3bbdc5ab5b Implemented chorus fruit 2017-12-23 15:11:48 +00:00
082e3404c3 Potion: Implement potion effects 2017-12-23 15:07:39 +00:00
547833ae23 Effect: Add constants with vanilla names where missing 2017-12-23 14:48:56 +00:00
6e1df36188 Consumables refactor (#1796)
* Removed broken EntityEatEvents - these don't fit the pattern since they only apply to Human entities anyway. PlayerItemConsumeEvent and PlayerInteractEvent can be used for cancellation purposes, and plugins can do custom stuff without mess.

* Restrict item consuming to Living entities only

* Added FoodSource->requiresHunger()

* Only items implementing the Consumable interface can now be consumed.

* The effects from consuming items are now generic-ized by way of the Living->consume() function. This is overridden in Human to allow applying food and hunger.

* Fixed the hardcoded mess for buckets
2017-12-23 13:03:41 +00:00
329fe7d844 Effect: Implement Saturation effect
I thought I did this months ago, but apparently not. Whatever, it's here now.
2017-12-23 11:35:01 +00:00
b7aaf54a6f Effect: Fixed mistake in bitshifting with effect level in instant effects
This should be the amplifier, otherwise the effect will have double-effect on level 1.
2017-12-23 11:32:58 +00:00
6332814a04 Effect: Minor cleanup on Instant Health/Damage effect amplification 2017-12-23 11:23:29 +00:00
9d4818d360 Effect: Hunger is supposed to apply every tick
This fixes oddities in the behaviour noticeable with higher effect levels.
2017-12-23 11:15:23 +00:00
36f3accf4b Effect: Don't allow cancellation of expired effect removal, close #1770 2017-12-23 10:55:25 +00:00
8d08840ea4 Effect: Better fix for duration bug seen in 3614711a02 2017-12-23 10:45:59 +00:00
7f0d0c9d63 Revert "fixed negative effect durations when level tick rate is > 1"
This reverts commit 3614711a02.
2017-12-23 10:44:21 +00:00
bf55f03a3e Merge pull request #1842 from pmmp/issues/983-interact-fix
Fix direction checking for player interactions, close #983
2017-12-23 09:42:39 +00:00
a5c3fbdd7a Player: Remove obsolete maxDiff parameter from canInteract() 2017-12-22 20:38:39 +00:00
a8bf2191b9 Player: Do direction checks for interaction in 3D instead of 2D
This fixes #983, but I haven't yet tested if this will prevent cheating in an actual hacker scenario. Needs more tests.

Additionally, this should remove the need for the negative threshold - if the diff is less than 0, the player is almost definitely cheating.
2017-12-22 20:06:59 +00:00
0688a86f57 Player: Fixed interaction checks preventing placing blocks when stood on the corner of one when using crosshairs
This issue can be seen on W10 Edition. Stand on the corner of a block and turn so that the majority of the target block is behind you. Then look down and try to mine it.
2017-12-22 19:58:33 +00:00
2e11e448dd Player: Dump crafting grid on death, not on respawn
This fixes players managing to retain items by getting killed while they have something in the crafting grid.
2017-12-22 11:34:33 +00:00
8bf275cb8b Player: Execute PlayerPreLoginEvent before banlist/whitelist checks, close #1831 (#1833) 2017-12-22 11:19:56 +00:00
1896576a24 ResourcePackManager: Remove Server constructor dependency 2017-12-22 11:11:58 +00:00
8f811c29d7 ResourcePackManager: Remove redundant config property
This was only used in the constructor, there's no need to store it.
2017-12-22 11:05:47 +00:00
3a4f79629c ResourcePackManager: Add API method getPath() 2017-12-22 11:04:15 +00:00
375243860e Potion: Restrict item stack size to 1 2017-12-21 15:02:56 +00:00
a842a5319f Enchantment: Create constant name once, and reuse it
this is more readable and more maintainable.
2017-12-21 13:11:31 +00:00
c2b0f6af22 Enchantment: Simplify getEnchantment() with null coalesce
This is made possible by 0e538ee51d.
2017-12-21 13:02:24 +00:00
6490d99ac2 Enchantment: Added a TODO (calculating XP min/max level cost bounds) 2017-12-21 12:55:55 +00:00
e0b063ac85 Enchantment: Added max level property 2017-12-21 12:49:34 +00:00
12ac2f4ac7 Enchantment: Fixed rarity constant values to match vanilla
Rarity is used for "weighting" enchantments on enchantment tables and such. Therefore higher numbers mean the enchantment is more common. This changes the rarity values to match vanilla.
2017-12-21 12:48:35 +00:00
cc1951c7ba Enchantment: Remove activation type stuff
This isn't and won't be used anywhere.
2017-12-21 12:48:14 +00:00
0e538ee51d Enchantment: Split up enchantment type data and enchantment instance data (#1825)
* Enchantment: Split enchantment type data from instance data
This commit splits enchantments into (effectively) enchantment TYPES vs enchantment INSTANCES.

When applying an enchantment to an item, it only needs to know 2 things:
1. the enchantment ID (identifier) which is used to identify the TYPE
2. the enchantment LEVEL which is used to modify the enchantment's power IN THIS INSTANCE.

Therefore, the LEVEL is not an immutable property. However, all other properties of the currently-named "Enchantment" class are immutable type properties.
Currently, when applying an enchantment to an item, a copy of the enchantment object is created from the registry, and returned. This copies all of the properties contained by the type, which is obviously sub optimal.
2017-12-21 12:40:33 +00:00
1b4b832c8c Added a getEntry() to BanList (#1830) 2017-12-21 10:08:56 +00:00
4f8e4f0522 Add EOF newlines where missing (bulk) (#1836)
This should solve issues with people making GitHub PRs and having the web editor messing things up. GitHub Web Editor sucks :(
2017-12-20 11:56:36 +00:00
0ee78d2416 Update DevTools submodule, fix build 2017-12-17 15:01:05 +00:00
4c46087ffc TextFormat: Added EOL constant (for MCPE)
MCPE always uses LF for line endings. PHP_EOL might be LF, CRLF, or CR depending on the platform, so it should not be used for (for example) sending messages to players containing newlines.
2017-12-17 14:58:37 +00:00
bb3e72ea4b StringTag: Fixed bad error message for bad value type 2017-12-17 12:30:18 +00:00
914e4c9a72 Enchantment: Fix formatting issue 2017-12-16 13:04:25 +00:00
9fd7312629 EnchantCommand: Fix vanilla translation
This parameter isn't required server side, but it doesn't matter anyway.
2017-12-16 10:34:38 +00:00
24387d1efe Enchantment: Add some PhpDoc for fields 2017-12-16 10:01:42 +00:00
3853938ef3 Level: Manage block cache appropriately when loading/unloading/replacing chunks, close #1813 (#1823)
This changes the block cache to be a 2-dimensional hashmap of [chunkHash][blockHash]. This is needed to more effectively dispose of chunk-specific block caches when chunks are modified.

This now destroys the cache for specific chunk indexes in the following circumstances:
- When a chunk is unloaded (the cache isn't needed anymore)
- When a chunk is set into the world (for example, from the generator)
- When a chunk is loaded (probably unnecessary)

This resolves the ghost blocks bug many have been complaining about.
2017-12-16 09:49:48 +00:00
4ec8416f9a Level: Fix minor code duplication in setChunk() 2017-12-15 16:47:59 +00:00
8aff793a4f Fix drops for leaves, close #1821
Seems that leaves are another special case - they technically speaking accept any tool to break, but only drop when shears are used. They don't REQUIRE shears because if they did the break time would be longer for non-shears tools.
2017-12-15 10:14:24 +00:00
d93ded9047 merge 1.2.7 "changes" 2017-12-14 18:59:11 +00:00
fbd04b0fe7 Bump to 1.2.7 2017-12-14 18:56:32 +00:00
953f45c50f Altered armour handling, now works for damage other than PvP 2017-12-14 12:37:28 +00:00
1822abc862 Living: Apply absorption after effect damage reduction is checked 2017-12-14 12:03:12 +00:00
92e966686e Refactor Living->attack() into several methods 2017-12-14 11:39:05 +00:00
3f50f88e2c Player: Cleaned up how hurt animations are handled
Override Living->doHitAnimation() instead to ensure that the animation always gets sent to the player.
2017-12-14 11:34:09 +00:00
532600ab67 Player: Remove another redundant attack check
This is checked in Player->attack() anyway.
2017-12-14 11:03:13 +00:00
78f8fe602c Player: Remove redundant PvP check
This is already checked in a block lower down.
2017-12-14 10:59:17 +00:00
e75fbd7fb4 Changed Effect colours to use Color objects instead of arrays (#1814) 2017-12-14 10:21:07 +00:00
06f605879a Effect: Save and restore ambiency properly 2017-12-14 10:10:26 +00:00
4c7038f941 Effect: Added proper documentation on "ambiency" 2017-12-14 09:57:20 +00:00
4bd4d42b82 Fixed raw porkchop being inedible 2017-12-14 09:09:47 +00:00
f5ebfc3418 Effect: Added Fatal Poison effect
This is identical to normal Poison, except that it kills the victim. Parrots receive this effect when they are fed cookies.
2017-12-13 18:59:49 +00:00
4ae278686c Player: Hack anti-fly to ignore levitation 2017-12-13 18:50:56 +00:00
740786c99e PillarRotationHelper: Drop redundant commit 2017-12-13 18:39:16 +00:00
6abf880e44 Block: Drop unnecessary parameters for ItemFactory::get() 2017-12-13 18:37:04 +00:00
853411fa4f Merge pull request #1795 from pmmp/tools-refactor
Tools refactor
2017-12-13 18:04:12 +00:00
6e30d23254 Added missing properties for several blocks 2017-12-13 16:28:21 +00:00
717b36a983 Cleaned up non-trivial getDrops() stuff 2017-12-13 14:47:50 +00:00
90eed14cd6 Fixed cobweb drops 2017-12-13 14:46:58 +00:00
4452e6ac93 Merge branch 'master' into tools-refactor 2017-12-13 12:58:50 +00:00
56f1a6ba37 Block: Migrated all trivial drops code to getDropsForCompatibleTool()
getDrops() should now be overridden only for special cases. There are some non-trivial overrides left that are going to need some extra work to clean up.
2017-12-13 12:49:58 +00:00
8c47a338df Block: Remove unused imports 2017-12-13 12:44:21 +00:00
7c6535283e SnowLayer: Fixed tool requirement 2017-12-13 12:39:29 +00:00
c669819bbb Fixed stained/hardened clay being harvestable without a pickaxe, close #1803 2017-12-13 12:01:46 +00:00
50f3231629 Fixed being able to mine double stone slabs without a pickaxe 2017-12-13 11:34:41 +00:00
015cde2169 Merge branch 'master' into tools-refactor 2017-12-13 11:26:24 +00:00
b9b50dd5dc Added Block->getDropsForCompatibleTool(), removed lots of boilerplate code from subclasses
The function name is a little long-winded, but that can always be refactored later if needed. This provides a way for blocks requiring specific tools to override drops with non-standard stuff without needing to worry about what tool type was used.

It's also possible that passing the Item used here is actually entirely redundant, but again that can be fixed later.
2017-12-12 20:02:50 +00:00
da3640357c Rename Block->canBeBrokenWith() to isCompatibleWithTool() and add documentation
This name better describes it. "can be broken with" implies that items which this returns false for cannot destroy the block at all, which is incorrect. What this actually returns is whether the item is the best tool to use to break the block.
2017-12-12 19:51:31 +00:00
0004e7429f Added some documentation on harvest level properties 2017-12-12 16:55:00 +00:00
e2e6b7516a Removed WoodenTool classes
These were only needed for their fuel properties, which are the same for all tools of the wooden tier anyway.
2017-12-12 13:55:38 +00:00
b903161a5d Refactored tool efficiency handling
This fixes lots of bugs with things like wool, cobwebs, swords.
2017-12-12 13:55:36 +00:00
99fe63b2a3 Added harvest level properties to applicable blocks
this fixes block-breaking animations with wrong tools, and also finally resolves the long-standing hierarchy problem in Stair.
2017-12-12 13:54:17 +00:00
dbc180315e Declare tool harvest level as a property 2017-12-12 13:54:16 +00:00
45983acc0d Fixed too-fast break times with wrong tool types 2017-12-12 13:54:16 +00:00
a02af1053f Remove redundant overrides from WoodenTools 2017-12-12 13:54:16 +00:00
7de88b9040 Tool tier efficiency should still apply if the block can't be harvested
If you use an iron pickaxe on obsidian, it still mines faster because the tool types are compatible, even though the tool is not high enough.
2017-12-12 13:54:06 +00:00
58327d0514 Change block tool types to bitflags
This allows specification of multiple tool types for a block, such as cobwebs.
2017-12-12 13:51:33 +00:00
db31d13f96 Added Item->getBlockToolType() 2017-12-12 13:45:52 +00:00
55d0684565 Move block-breaking tool-type constants to a BlockToolType interface 2017-12-12 13:45:52 +00:00
7e3cd24444 Added TieredTool->getTier() 2017-12-12 13:45:51 +00:00
2088a43c56 Refactored tool hierarchy 2017-12-12 13:45:51 +00:00
738 changed files with 5535 additions and 8134 deletions

View File

@ -33,4 +33,8 @@ Requires translations:
-->
## Tests
<!-- Attach scripts or actions to test this pull request, as well as the result -->
<!--
Details should be provided of tests done. Simply saying "tested" or equivalent is not acceptable.
Attach scripts or actions to test this pull request, as well as the result
-->

3
.gitignore vendored
View File

@ -1,8 +1,9 @@
players/*
worlds/*
plugins/*
bin/*
bin*/*
timings/*
crashdumps/*
*.log
*.txt
*.phar

View File

@ -8,7 +8,7 @@ before_script:
- echo | pecl install channel://pecl.php.net/yaml-2.0.2
- git clone https://github.com/krakjoe/pthreads.git
- cd pthreads
- git checkout 6c6b15138c923b69cfa46ee05fc2dd45da587287
- git checkout d32079fb4a88e6e008104d36dbbf0c2dd7deb403
- phpize
- ./configure
- make

View File

@ -5,58 +5,48 @@
## Creating an Issue
- If you are reporting a bug:
- **make sure that you are using the latest supported version** before opening an issue.
- **test it on a clean test server, WITHOUT PLUGINS**, to see if the issue still occurs. If not then it may be a plugin issue. Please also indicate the result of such tests.
- [Search the issue tracker](https://github.com/pmmp/PocketMine-MP/issues?utf8=%E2%9C%93&q=is%3Aissue) to check if anyone has already reported it, to avoid needlessly creating duplicate issues. Make sure you also check closed issues, as an issue you think is valid may already have been resolved.
- If your issue is related to a plugin, **do not report here, contact the plugin's original author** instead.
- **make sure that you are using the latest supported version** before opening an issue.
- **test it on a clean test server, WITHOUT PLUGINS**, to see if the issue still occurs. If not then it may be a plugin issue. Please also indicate the result of such tests.
- **[Search the issue tracker](https://github.com/pmmp/PocketMine-MP/issues?utf8=%E2%9C%93&q=is%3Aissue)** to check if anyone has already reported it, to avoid needlessly creating duplicate issues. Make sure you also check closed issues, as an issue you think is valid may already have been resolved.
- **Do not report plugin issues here.** If your issue is related to a plugin, contact the plugin's original author instead.
- **Support requests are not bugs.** Issues such as "How do I do this" are not bugs and will be closed. If you need help, please see [here](README.md#discussion) and do not misuse our issue tracker.
- **No generic titles** such as "Question", "Help", "Crash Report" etc. A good issue report provides a quick summary in the title. If you just got a crash report but you don't understand it, please look for a line starting with `Message`. It summarizes the bug.
- Information must be provided in the issue body, not in the title. No tags like `[BUG]` are allowed in the title, including `[SOLVED]` for solved issues.
- Similarly, no generic issue reports. For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**.
<br><br>Valid issue reports must include instructions how to reproduce the issue or a crashdump/backtrace (unless the cause of the issue is obvious).
<br><br>**If you do not provide us with a summary or instructions on how to reproduce the issue, it will be treated as spam and will therefore be closed.**
<br><br>In simple words, if the issue cannot be properly confirmed to be valid or lacks required information, the issue will be closed until further information is provided.
- **Provide information in the issue body, not in the title.** No tags like `[BUG]` are allowed in the title, including `[SOLVED]` for solved issues.
- **No generic issue reports.** For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**.
<br>Valid issue reports must include instructions how to reproduce the issue or a crashdump/backtrace (unless the cause of the issue is obvious).
<br>**If you do not provide us with a summary or instructions on how to reproduce the issue, it will be treated as spam and will therefore be closed.**
<br>In simple words, if the issue cannot be properly confirmed to be valid or lacks required information, the issue will be closed until further information is provided.
- To express appreciation, objection, confusion or other supported reactions on pull requests, issues or comments on them, use GitHub [reactions](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) rather than posting an individual comment with an emoji only. This helps keeping the issue/pull request conversation clean and readable.
- If your issue is related to the PocketMine-MP website, forums, etc., please [talk to a human directly](README.md#discussion).
## Contributing Code
- To contribute code to the repository, [fork it on GitHub](https://github.com/pmmp/PocketMine-MP/fork), create a branch on your fork, and make your changes on your fork. You can then make a [pull request](https://github.com/pmmp/PocketMine-MP/pull/new) to the project to compare your branch to ours and propose your changes to our repository. We use the Pull Request system to allow members of the team to review changes before they are merged.
## Contributing
To contribute to the repository, [fork it on GitHub](https://github.com/pmmp/PocketMine-MP/fork), create a branch on your fork, and make your changes on your fork. You can then make a [pull request](https://github.com/pmmp/PocketMine-MP/pull/new) to the project to compare your branch to ours and propose your changes to our repository. We use the Pull Request system to allow members of the team to review changes before they are merged.
- By proposing a pull request to the project, you agree to your code being distributed within PocketMine-MP under the [LGPL license](LICENSE).
### Licensing
By proposing a pull request to the project, you agree to your code being distributed within PocketMine-MP under the [LGPL license](LICENSE).
- At PocketMine, **we enforce a very high standard for contributions**. This is because PocketMine-MP and its related projects are used very widely in production. While this might seem like we are being mean at times, **our priority is what is best for PocketMine-MP itself**. We try to ensure that our project's codebase is as clean as possible and ensure that only top-quality material makes it through to PocketMine-MP itself. **If a contribution does not live up to our standards, changes may be requested or the pull request may be closed.**
- **Your pull request will be checked and discussed in due time.** Since the team is scattered all around the world, your PR may not receive any attention for some time.
- **Avoid using GitHub Web Editor**. The web editor lacks most useful GIT features and **should only be used for very minor changes**. It is immediately clear if the web editor has been used, and if so the PR is more likely to be rejected. If you want to make serious contributions, **please learn how to use [GIT version control](https://git-scm.com/)**.
- **Do not copy-paste code**. There are potential license issues implicit with copy-pasting, and copy-paste usually indicates a lack of understanding of the actual code. Copy-pasted code is obvious a mile off and **any PR like this is likely to be closed**. If you want to use somebody else's code from a Git repository, **use [GIT's cherry-pick feature](https://git-scm.com/docs/git-cherry-pick)** to cherry-pick the commit. **Cherry-picking is the politer way to copy somebody's changes** and retains all the original accreditation, so there is no need for copy-pasted commits with descriptions like `Some code, thanks @exampleperson`.
- In addition to the above, **make sure you can explain your changes**. If you can't provide a good explanation of changes, your PR may be rejected.
### Contribution standards
- **We enforce a very high standard for contributions**. This is because PocketMine-MP and its related projects are used very widely in production. While this might seem like we are being mean at times, **our priority is what is best for PocketMine-MP itself**.
We try to ensure that our project's codebase is as clean as possible and ensure that only top-quality material makes it through to PocketMine-MP itself.
- **If a contribution does not meet our standards, changes may be requested or the pull request may be closed.**
### Pull requests
- **Create a new branch for each pull request.** Do not create a pull request with commits that exist in another pull request.
- **Code should use the same style as in PocketMine-MP.** See [below](#code-syntax) for an example.
- **The code must be clear** and written in English, comments included.
- **Use descriptive commit titles.** You can see an example [here](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
- **Try to stick to one change per commit.** This ensures that if you create a PR with several changes, we can decide which ones we wish to include and which ones not to include.
- **It is inadvisable to create pull requests with large commits** unless this has been discussed with the team beforehand. Large pull requests are difficult to review, and such pull requests may end up being closed. The only exception is when all features in the pull request are related to each other, and share the same core changes.
- **Do not include multiple unrelated changes in one commit.** An atomic style for commits is preferred - this means that changes included in a commit should be part of a single distinct change set. See [this link](https://www.freshconsulting.com/atomic-commits/) for more information on atomic commits. See the [documentation on `git add`](https://git-scm.com/docs/git-add) for information on how to isolate local changes for committing.
- **Your pull request will be checked and discussed in due time.** Since the team is scattered all around the world, your PR may not receive any attention for some time.
- **It is inadvisable to create large pull requests with lots of changes** unless this has been discussed with the team beforehand. Large pull requests are difficult to review, and such pull requests may end up being closed. The only exception is when all features in the pull request are related to each other, and share the same core changes.
- **You may be asked to rebase your pull request** if the branch becomes outdated and/or if possibly conflicting changes are made to the target branch. To see how to do this, read [this page](https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request).
- **Details should be provided of tests done.** Simply saying "Tested" or equivalent is not acceptable.
### Code contributions
- **Avoid using GitHub Web Editor**. The web editor lacks most useful GIT features and **should only be used for very minor changes**. It is immediately clear if the web editor has been used, and if so the PR is more likely to be rejected. If you want to make serious contributions, **please learn how to use [GIT version control](https://git-scm.com/)**.
- **Do not copy-paste code**. There are potential license issues implicit with copy-pasting, and copy-paste usually indicates a lack of understanding of the actual code. Copy-pasted code is obvious a mile off and **any PR like this is likely to be closed**. If you want to use somebody else's code from a Git repository, **use [GIT's cherry-pick feature](https://git-scm.com/docs/git-cherry-pick)** to cherry-pick the commit. **Cherry-picking is the politer way to copy somebody's changes** and retains all the original accreditation, so there is no need for copy-pasted commits with descriptions like `Some code, thanks @exampleperson`.
- **Make sure you can explain your changes**. If you can't provide a good explanation of changes, your PR may be rejected.
- **Code should use the same style as in PocketMine-MP.** See [below](#code-syntax) for an example.
- **The code must be clear** and written in English, comments included.
**Thanks for contributing to PocketMine-MP!**
@ -78,17 +68,18 @@ It is mainly [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accept
- Strings SHOULD use the double quote `"` except when the single quote is required.
- All code SHOULD have parameter and type declarations where possible.
- Strict types SHOULD be enabled on new files where it is sensible to do so.
- All constant declarations SHOULD be preceded by a visibility modifier.
```php
<?php
declare(strict_types = 1);
declare(strict_types=1);
namespace pocketmine\example;
class ExampleClass{
const EXAMPLE_CLASS_CONSTANT = 1;
public const EXAMPLE_CLASS_CONSTANT = 1;
public $examplePublicVariable = "defaultValue";
private $examplePrivateVariable;
@ -99,7 +90,7 @@ class ExampleClass{
* @param string $firstArgument the first argument
* @param string|null $secondArgument default null
*/
public function __construct(string $firstArgument, &$secondArgument = null){
public function __construct(string $firstArgument, ?string &$secondArgument = null){
if($firstArgument === "exampleValue"){ //Remember to use === instead of == when possible
//do things
}elseif($firstArgument === "otherValue"){
@ -119,7 +110,6 @@ class ExampleClass{
public function doStuff(string $stuff) : string{
return $stuff;
}
}
```
@ -133,4 +123,4 @@ class ExampleClass{
* After voting has been closed, no further votes will be counted.
* An RFC will be rejected if less than 50% + 1 (simple majority) has voted Yes.
* If the RFC is approved, Team Members have the final word on its implementation or rejection.
* RFCs with complex voting options will specify the vote percentage or other details.
* RFCs with complex voting options will specify the vote percentage or other details.

View File

@ -10,7 +10,6 @@ If you don't find what you're looking for there, [talk to a human](#discussion).
### Discussion
- [Forums](https://forums.pmmp.io/)
- [#pmmp + #pocketmine channel IRC](http://webchat.freenode.net/?channels=pmmp,pocketmine)
### Plugins
There are a very wide range of already-written plugins available which you can use to customise your server. Check out [Poggit](https://poggit.pmmp.io), or just search GitHub.
@ -23,7 +22,10 @@ There are a very wide range of already-written plugins available which you can u
Yes you can! Contributions are welcomed provided that they comply with our [Contributing Guidelines](CONTRIBUTING.md). Please ensure you read the relevant sections of the guidelines carefully before making a Pull Request or opening an Issue.
### Where can I get the latest .phar?
Head over to our [official Jenkins server](https://jenkins.pmmp.io/)
- Latest release builds can be found in our [GitHub releases](https://github.com/pmmp/PocketMine-MP/releases).
- Latest bleeding-edge development builds (and other builds in the build job channels) can be found on our [Jenkins server](https://jenkins.pmmp.io/).
**Note: Please avoid development builds unless there is no other alternative for what you need.** Development builds are subject to changes at any time without notice, and it is likely that your server or plugins might break without warning.
## Third-party Libraries/Protocols Used
* __[PHP Sockets](http://php.net/manual/en/book.sockets.php)__

View File

@ -1,5 +1,5 @@
{
"name": "pmmp/pocketmine-mp",
"name": "pocketmine/pocketmine-mp",
"description": "A server software for Minecraft: Pocket Edition written in PHP",
"type": "project",
"homepage": "https://pmmp.io",
@ -21,8 +21,10 @@
"ext-yaml": ">=2.0.0",
"ext-zip": "*",
"ext-zlib": ">=1.2.11",
"pmmp/raklib": "dev-master#29ab14d5d8640a8ee359ce315b083a129e72db4a",
"pmmp/pocketmine-spl": "^0.1.0"
"pocketmine/raklib": "dev-master#eaa85c2b23bbc1a85030a621d4644c0e33e05950",
"pocketmine/pocketmine-spl": "^0.2.0",
"pocketmine/pocketmine-binaryutils": "dev-master#a7cd5303a3b215d26bf9be76682ce9311f40e887",
"pocketmine/pocketmine-nbt": "dev-master#f8934c0aed90d1f55452588f7ebef7c4519518a5"
},
"autoload": {
"psr-0": {
@ -37,6 +39,14 @@
{
"type": "vcs",
"url": "https://github.com/pmmp/PocketMine-SPL"
},
{
"type": "vcs",
"url": "https://github.com/pmmp/PocketMine-BinaryUtils"
},
{
"type": "vcs",
"url": "https://github.com/pmmp/PocketMine-NBT"
}
]
}

100
composer.lock generated
View File

@ -4,20 +4,87 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "169d2724a6847e704f3bb76030bebc87",
"content-hash": "5997f272811ed1148e7699a33335a0d2",
"packages": [
{
"name": "pmmp/pocketmine-spl",
"version": "0.1.0",
"name": "pocketmine/pocketmine-binaryutils",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/pmmp/PocketMine-SPL.git",
"reference": "c56936e6aaad925bb60002b29b1c70f497af4679"
"url": "https://github.com/pmmp/PocketMine-BinaryUtils.git",
"reference": "a7cd5303a3b215d26bf9be76682ce9311f40e887"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/PocketMine-SPL/zipball/c56936e6aaad925bb60002b29b1c70f497af4679",
"reference": "c56936e6aaad925bb60002b29b1c70f497af4679",
"url": "https://api.github.com/repos/pmmp/PocketMine-BinaryUtils/zipball/a7cd5303a3b215d26bf9be76682ce9311f40e887",
"reference": "a7cd5303a3b215d26bf9be76682ce9311f40e887",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"type": "library",
"autoload": {
"psr-4": {
"pocketmine\\utils\\": "src/"
}
},
"license": [
"LGPL-3.0"
],
"description": "Classes and methods for conveniently handling binary data",
"support": {
"source": "https://github.com/pmmp/PocketMine-BinaryUtils/tree/master",
"issues": "https://github.com/pmmp/PocketMine-BinaryUtils/issues"
},
"time": "2018-01-14T18:53:25+00:00"
},
{
"name": "pocketmine/pocketmine-nbt",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/pmmp/PocketMine-NBT.git",
"reference": "f8934c0aed90d1f55452588f7ebef7c4519518a5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/PocketMine-NBT/zipball/f8934c0aed90d1f55452588f7ebef7c4519518a5",
"reference": "f8934c0aed90d1f55452588f7ebef7c4519518a5",
"shasum": ""
},
"require": {
"php": ">=7.2.0",
"pocketmine/pocketmine-binaryutils": "dev-master#8bb34e771fee69abcc5482d17d2fa0b4f0e15a5e"
},
"type": "library",
"autoload": {
"psr-4": {
"pocketmine\\nbt\\": "src/"
}
},
"license": [
"LGPL-3.0"
],
"description": "PHP library for working with Named Binary Tags",
"support": {
"source": "https://github.com/pmmp/PocketMine-NBT/tree/master",
"issues": "https://github.com/pmmp/PocketMine-NBT/issues"
},
"time": "2018-01-11T13:51:50+00:00"
},
{
"name": "pocketmine/pocketmine-spl",
"version": "0.2.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/PocketMine-SPL.git",
"reference": "70c591a44b6c5aa541a1a55585764bed2b23148c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/PocketMine-SPL/zipball/70c591a44b6c5aa541a1a55585764bed2b23148c",
"reference": "70c591a44b6c5aa541a1a55585764bed2b23148c",
"shasum": ""
},
"type": "library",
@ -36,20 +103,20 @@
"support": {
"source": "https://github.com/pmmp/PocketMine-SPL/tree/master"
},
"time": "2017-12-10T12:18:30+00:00"
"time": "2018-01-11T13:03:01+00:00"
},
{
"name": "pmmp/raklib",
"name": "pocketmine/raklib",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/pmmp/RakLib.git",
"reference": "29ab14d5d8640a8ee359ce315b083a129e72db4a"
"reference": "eaa85c2b23bbc1a85030a621d4644c0e33e05950"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/29ab14d5d8640a8ee359ce315b083a129e72db4a",
"reference": "29ab14d5d8640a8ee359ce315b083a129e72db4a",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/eaa85c2b23bbc1a85030a621d4644c0e33e05950",
"reference": "eaa85c2b23bbc1a85030a621d4644c0e33e05950",
"shasum": ""
},
"require": {
@ -57,7 +124,8 @@
"ext-pthreads": ">=3.1.7dev",
"ext-sockets": "*",
"php": ">=7.2.0RC3",
"pmmp/pocketmine-spl": "^0.1.0"
"pocketmine/pocketmine-binaryutils": "dev-master#a7cd5303a3b215d26bf9be76682ce9311f40e887",
"pocketmine/pocketmine-spl": "^0.2.0"
},
"type": "library",
"autoload": {
@ -73,7 +141,7 @@
"source": "https://github.com/pmmp/RakLib/tree/master",
"issues": "https://github.com/pmmp/RakLib/issues"
},
"time": "2017-12-10T12:24:38+00:00"
"time": "2018-01-27T15:38:43+00:00"
}
],
"packages-dev": [],
@ -82,7 +150,9 @@
"stability-flags": {
"php": 5,
"ext-pthreads": 20,
"pmmp/raklib": 20
"pocketmine/raklib": 20,
"pocketmine/pocketmine-binaryutils": 20,
"pocketmine/pocketmine-nbt": 20
},
"prefer-stable": false,
"prefer-lowest": false,

View File

@ -186,7 +186,7 @@ class CrashDump{
$this->addLine("Line: " . $error["line"]);
$this->addLine("Type: " . $error["type"]);
if(strpos($error["file"], "src/pocketmine/") === false and strpos($error["file"], "src/raklib/") === false and file_exists($error["fullFile"])){
if(strpos($error["file"], "src/pocketmine/") === false and strpos($error["file"], "vendor/pocketmine/") === false and file_exists($error["fullFile"])){
$this->addLine();
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
$this->data["plugin"] = true;
@ -257,4 +257,4 @@ class CrashDump{
fwrite($this->fp, $str);
}
}
}

View File

@ -265,7 +265,7 @@ class MemoryManager{
*/
public function dumpServerMemory(string $outputFolder, int $maxNesting, int $maxStringSize){
MainLogger::getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
self::dumpMemory($this->server, $this->server->getLoader(), $outputFolder, $maxNesting, $maxStringSize);
self::dumpMemory($this->server, $outputFolder, $maxNesting, $maxStringSize);
if($this->dumpWorkers){
$scheduler = $this->server->getScheduler();
@ -278,13 +278,14 @@ class MemoryManager{
/**
* Static memory dumper accessible from any thread.
*
* @param mixed $startingObject
* @param \ClassLoader $loader
* @param string $outputFolder
* @param int $maxNesting
* @param int $maxStringSize
* @param mixed $startingObject
* @param string $outputFolder
* @param int $maxNesting
* @param int $maxStringSize
*
* @throws \ReflectionException
*/
public static function dumpMemory($startingObject, \ClassLoader $loader, string $outputFolder, int $maxNesting, int $maxStringSize){
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize){
$hardLimit = ini_get('memory_limit');
ini_set('memory_limit', '-1');
gc_disable();
@ -306,7 +307,7 @@ class MemoryManager{
$staticProperties = [];
$staticCount = 0;
foreach($loader->getClasses() as $className){
foreach(get_declared_classes() as $className){
$reflection = new \ReflectionClass($className);
$staticProperties[$className] = [];
foreach($reflection->getProperties() as $property){
@ -330,7 +331,7 @@ class MemoryManager{
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
MainLogger::getLogger()->info("[Dump] Wrote $staticCount static properties");
if($GLOBALS !== null){ //This might be null if we're on a different thread
if(isset($GLOBALS)){ //This might be null if we're on a different thread
$globalVariables = [];
$globalCount = 0;

View File

@ -74,12 +74,11 @@ use pocketmine\inventory\BigCraftingGrid;
use pocketmine\inventory\CraftingGrid;
use pocketmine\inventory\Inventory;
use pocketmine\inventory\PlayerCursorInventory;
use pocketmine\inventory\PlayerInventory;
use pocketmine\inventory\transaction\action\InventoryAction;
use pocketmine\inventory\transaction\CraftingTransaction;
use pocketmine\inventory\transaction\InventoryTransaction;
use pocketmine\item\Consumable;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\WritableBook;
use pocketmine\item\WrittenBook;
use pocketmine\level\ChunkLoader;
@ -89,10 +88,9 @@ use pocketmine\level\Location;
use pocketmine\level\Position;
use pocketmine\level\WeakPosition;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector2;
use pocketmine\math\Vector3;
use pocketmine\metadata\MetadataValue;
use pocketmine\nbt\NBT;
use pocketmine\nbt\NetworkLittleEndianNBTStream;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\DoubleTag;
@ -202,15 +200,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
public $spawned = false;
public $loggedIn = false;
public $gamemode;
public $lastBreak;
/** @var bool */
protected $authenticated = false;
/** @var string */
protected $xuid = "";
protected $windowCnt = 2;
/** @var \SplObjectStorage<Inventory> */
protected $windows;
/** @var int[] */
protected $windows = [];
/** @var Inventory[] */
protected $windowIndex = [];
/** @var bool[] */
@ -281,7 +278,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
protected $flying = false;
protected $allowMovementCheats = false;
protected $allowInstaBreak = false;
private $needACK = [];
@ -440,14 +436,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->allowMovementCheats = $value;
}
public function allowInstaBreak() : bool{
return $this->allowInstaBreak;
}
public function setAllowInstaBreak(bool $value = true){
$this->allowInstaBreak = $value;
}
/**
* @param Player $player
*/
@ -526,6 +514,10 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return false;
}
public function canBeCollidedWith() : bool{
return !$this->isSpectator();
}
public function resetFallDistance(){
parent::resetFallDistance();
if($this->inAirTicks !== 0){
@ -692,11 +684,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
*/
public function __construct(SourceInterface $interface, $clientID, string $ip, int $port){
$this->interface = $interface;
$this->windows = new \SplObjectStorage();
$this->perm = new PermissibleBase($this);
$this->namedtag = new CompoundTag();
$this->server = Server::getInstance();
$this->lastBreak = PHP_INT_MAX;
$this->ip = $ip;
$this->port = $port;
$this->clientID = $clientID;
@ -707,13 +697,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->setLevel($this->server->getDefaultLevel());
$this->boundingBox = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
$this->uuid = null;
$this->rawUUID = null;
$this->creationTime = microtime(true);
$this->allowMovementCheats = (bool) $this->server->getProperty("player.anti-cheat.allow-movement-cheats", false);
$this->allowInstaBreak = (bool) $this->server->getProperty("player.anti-cheat.allow-instabreak", false);
$this->sessionAdapter = new PlayerNetworkSessionAdapter($this->server, $this);
}
@ -1166,6 +1152,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return false;
}
$pos = $pos->floor();
$b = $this->level->getBlock($pos);
$this->server->getPluginManager()->callEvent($ev = new PlayerBedEnterEvent($this, $b));
@ -1179,12 +1166,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->sleeping = clone $pos;
$this->setDataProperty(self::DATA_PLAYER_BED_POSITION, self::DATA_TYPE_POS, [$pos->x, $pos->y, $pos->z]);
$this->propertyManager->setBlockPos(self::DATA_PLAYER_BED_POSITION, $pos);
$this->setPlayerFlag(self::DATA_PLAYER_FLAG_SLEEP, true);
$this->setSpawn($pos);
$this->level->sleepTicks = 60;
$this->level->setSleepTicks(60);
return true;
}
@ -1198,10 +1185,10 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->server->getPluginManager()->callEvent($ev = new PlayerBedLeaveEvent($this, $b));
$this->sleeping = null;
$this->setDataProperty(self::DATA_PLAYER_BED_POSITION, self::DATA_TYPE_POS, [0, 0, 0]);
$this->propertyManager->setBlockPos(self::DATA_PLAYER_BED_POSITION, null);
$this->setPlayerFlag(self::DATA_PLAYER_FLAG_SLEEP, false);
$this->level->sleepTicks = 0;
$this->level->setSleepTicks(0);
$pk = new AnimatePacket();
$pk->entityRuntimeId = $this->id;
@ -1433,6 +1420,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return [];
}
public function getXpDropAmount() : int{
if(!$this->isCreative()){
return parent::getXpDropAmount();
}
return 0;
}
protected function checkGroundState(float $movX, float $movY, float $movZ, float $dx, float $dy, float $dz){
if(!$this->onGround or $movY != 0){
$bb = clone $this->boundingBox;
@ -1660,6 +1655,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
if($this->spawned){
$this->processMovement($tickDiff);
$this->motionX = $this->motionY = $this->motionZ = 0; //TODO: HACK! (Fixes player knockback being messed up)
Timings::$timerEntityBaseTick->startTiming();
$this->entityBaseTick($tickDiff);
@ -1679,7 +1675,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$expectedVelocity = (-$this->gravity) / $this->drag - ((-$this->gravity) / $this->drag) * exp(-$this->drag * ($this->inAirTicks - $this->startAirTicks));
$diff = ($this->speed->y - $expectedVelocity) ** 2;
if(!$this->hasEffect(Effect::JUMP) and $diff > 0.6 and $expectedVelocity < $this->speed->y and !$this->server->getAllowFlight()){
if(!$this->hasEffect(Effect::JUMP) and !$this->hasEffect(Effect::LEVITATION) and $diff > 0.6 and $expectedVelocity < $this->speed->y and !$this->server->getAllowFlight()){
if($this->inAirTicks < 100){
$this->setMotion(new Vector3(0, $expectedVelocity, 0));
}elseif($this->kick($this->server->getLanguage()->translateString("kick.reason.cheat", ["%ability.flight"]))){
@ -1742,21 +1738,21 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
* Returns whether the player can interact with the specified position. This checks distance and direction.
*
* @param Vector3 $pos
* @param $maxDistance
* @param float $maxDiff
* @param float $maxDistance
* @param float $maxDiff defaults to half of the 3D diagonal width of a block
*
* @return bool
*/
public function canInteract(Vector3 $pos, $maxDistance, float $maxDiff = 0.5) : bool{
public function canInteract(Vector3 $pos, float $maxDistance, float $maxDiff = M_SQRT3 / 2) : bool{
$eyePos = $this->getPosition()->add(0, $this->getEyeHeight(), 0);
if($eyePos->distanceSquared($pos) > $maxDistance ** 2){
return false;
}
$dV = $this->getDirectionPlane();
$dot = $dV->dot(new Vector2($eyePos->x, $eyePos->z));
$dot1 = $dV->dot(new Vector2($pos->x, $pos->z));
return ($dot1 - $dot) >= -$maxDiff;
$dV = $this->getDirectionVector();
$eyeDot = $dV->dot($eyePos);
$targetDot = $dV->dot($pos);
return ($targetDot - $eyeDot) >= -$maxDiff;
}
protected function initHumanData(){
@ -1828,6 +1824,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->setSkin($skin);
$this->server->getPluginManager()->callEvent($ev = new PlayerPreLoginEvent($this, "Plugin reason"));
if($ev->isCancelled()){
$this->close("", $ev->getKickMessage());
return true;
}
if(!$this->server->isWhitelisted($this->iusername) and $this->kick("Server is white-listed", false)){
return true;
}
@ -1839,17 +1842,10 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return true;
}
$this->server->getPluginManager()->callEvent($ev = new PlayerPreLoginEvent($this, "Plugin reason"));
if($ev->isCancelled()){
$this->close("", $ev->getKickMessage());
return true;
}
if(!$packet->skipVerification){
$this->server->getScheduler()->scheduleAsyncTask(new VerifyLoginTask($this, $packet));
}else{
$this->onVerifyCompleted($packet, true, true);
$this->onVerifyCompleted($packet, null, true);
}
return true;
@ -1862,13 +1858,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->sendDataPacket($pk, false, $immediate);
}
public function onVerifyCompleted(LoginPacket $packet, bool $isValid, bool $isAuthenticated) : void{
public function onVerifyCompleted(LoginPacket $packet, ?string $error, bool $isAuthenticated) : void{
if($this->closed){
return;
}
if(!$isValid){
$this->close("", "disconnect.loginFailedInfo.invalidSession");
if($error !== null){
$this->close("", $this->server->getLanguage()->translateString("pocketmine.disconnect.invalidSession", [$error]));
return;
}
@ -1924,7 +1920,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
if(($level = $this->server->getLevelByName($this->namedtag->getString("Level", "", true))) === null){
$this->setLevel($this->server->getDefaultLevel());
$this->namedtag->setString("Level", $this->level->getName());
$this->namedtag->setString("Level", $this->level->getFolderName());
$spawnLocation = $this->level->getSpawnLocation();
$this->namedtag->setTag(new ListTag("Pos", [
new DoubleTag("", $spawnLocation->x),
@ -2078,7 +2074,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->sendData($this);
$this->inventory->sendContents($this);
$this->inventory->sendArmorContents($this);
$this->armorInventory->sendContents($this);
$this->inventory->sendCreativeContents();
$this->inventory->sendHeldItem($this);
@ -2148,8 +2144,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->isTeleporting = false;
}
$packet->yaw %= 360;
$packet->pitch %= 360;
$packet->yaw = fmod($packet->yaw, 360);
$packet->pitch = fmod($packet->pitch, 360);
if($packet->yaw < 0){
$packet->yaw += 360;
@ -2164,7 +2160,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
public function handleLevelSoundEvent(LevelSoundEventPacket $packet) : bool{
//TODO: add events so plugins can change this
$this->getLevel()->addChunkPacket($this->chunk->getX(), $this->chunk->getZ(), $packet);
if($this->chunk !== null){
$this->getLevel()->addChunkPacket($this->chunk->getX(), $this->chunk->getZ(), $packet);
}
return true;
}
@ -2245,6 +2243,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
switch($packet->transactionType){
case InventoryTransactionPacket::TYPE_NORMAL:
$this->setUsingItem(false);
$transaction = new InventoryTransaction($this, $actions);
if(!$transaction->execute()){
@ -2260,6 +2259,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
if(count($packet->actions) > 0){
$this->server->getLogger()->debug("Expected 0 actions for mismatch, got " . count($packet->actions) . ", " . json_encode($packet->actions));
}
$this->setUsingItem(false);
$this->sendAllInventories();
return true;
@ -2314,7 +2314,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$item = $this->inventory->getItemInHand();
$oldItem = clone $item;
if($this->canInteract($blockVector->add(0.5, 0.5, 0.5), $this->isCreative() ? 13 : 6) and $this->level->useBreakOn($blockVector, $item, $this, true)){
if($this->canInteract($blockVector->add(0.5, 0.5, 0.5), $this->isCreative() ? 13 : 7) and $this->level->useBreakOn($blockVector, $item, $this, true)){
if($this->isSurvival()){
if(!$item->equalsExact($oldItem)){
$this->inventory->setItemInHand($item);
@ -2399,34 +2399,18 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
$cancelled = false;
if($target instanceof Player and $this->server->getConfigBool("pvp", true) === false){
$cancelled = true;
}
$heldItem = $this->inventory->getItemInHand();
$damage = [
EntityDamageEvent::MODIFIER_BASE => $heldItem->getAttackPoints()
];
if(!$this->canInteract($target, 8)){
$cancelled = true;
}elseif($target instanceof Player){
if(($target->getGamemode() & 0x01) > 0){
return true;
}elseif($this->server->getConfigBool("pvp") !== true){
if($this->server->getConfigBool("pvp") !== true){
$cancelled = true;
}
$points = 0;
foreach($target->getInventory()->getArmorContents() as $armorItem){
$points += $armorItem->getDefensePoints();
}
$damage[EntityDamageEvent::MODIFIER_ARMOR] = -($damage[EntityDamageEvent::MODIFIER_BASE] * $points * 0.04);
}
$ev = new EntityDamageByEntityEvent($this, $target, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $damage);
$ev = new EntityDamageByEntityEvent($this, $target, EntityDamageEvent::CAUSE_ENTITY_ATTACK, $heldItem->getAttackPoints());
if($cancelled){
$ev->setCancelled();
}
@ -2465,52 +2449,40 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->inventory->setItemInHand($item);
}
}else{
$this->inventory->sendContents($this);
break;
}
return true;
case InventoryTransactionPacket::RELEASE_ITEM_ACTION_CONSUME:
$slot = $this->inventory->getItemInHand();
if($slot->canBeConsumed()){
if($slot instanceof Consumable){
$ev = new PlayerItemConsumeEvent($this, $slot);
if(!$slot->canBeConsumedBy($this)){
$ev->setCancelled();
}
$this->server->getPluginManager()->callEvent($ev);
if(!$ev->isCancelled()){
$slot->onConsume($this);
}else{
$this->inventory->sendContents($this);
}
return true;
}elseif($slot->getId() === Item::BUCKET and $slot->getDamage() === 1){ //Milk!
$this->server->getPluginManager()->callEvent($ev = new PlayerItemConsumeEvent($this, $slot));
if($ev->isCancelled()){
if($ev->isCancelled() or !$this->consumeObject($slot)){
$this->inventory->sendContents($this);
return true;
}
if($this->isSurvival()){
--$slot->count;
$slot->pop();
$this->inventory->setItemInHand($slot);
$this->inventory->addItem(ItemFactory::get(Item::BUCKET, 0, 1));
$this->inventory->addItem($slot->getResidue());
}
$this->removeAllEffects();
return true;
}
return false;
break;
default:
break;
}
}finally{
$this->setUsingItem(false);
}
$this->inventory->sendContents($this);
break;
default:
$this->inventory->sendContents($this);
@ -2606,7 +2578,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
switch($packet->action){
case PlayerActionPacket::ACTION_START_BREAK:
if($this->lastBreak !== PHP_INT_MAX or $pos->distanceSquared($this) > 10000){
if($pos->distanceSquared($this) > 10000){
break;
}
@ -2636,12 +2608,10 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_START_BREAK, (int) (65535 / $breakTime));
}
}
$this->lastBreak = microtime(true);
break;
/** @noinspection PhpMissingBreakStatementInspection */
case PlayerActionPacket::ACTION_ABORT_BREAK:
$this->lastBreak = PHP_INT_MAX;
case PlayerActionPacket::ACTION_STOP_BREAK:
$this->level->broadcastLevelEvent($pos, LevelEventPacket::EVENT_BLOCK_STOP_BREAK);
break;
@ -2661,8 +2631,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
break;
}
$this->resetCraftingGridType();
$this->server->getPluginManager()->callEvent($ev = new PlayerRespawnEvent($this, $this->getSpawn()));
$realSpawn = Position::fromObject($ev->getRespawnPosition()->add(0.5, 0, 0.5), $ev->getRespawnPosition()->getLevel());
@ -2698,7 +2666,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->sendSettings();
$this->inventory->sendContents($this);
$this->inventory->sendArmorContents($this);
$this->armorInventory->sendContents($this);
$this->spawnToAll();
$this->scheduleUpdate();
@ -2797,8 +2765,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->level->dropItem($this->add(0, 1.3, 0), $item, $motion, 40);
$this->setUsingItem(false);
return true;
}
@ -2866,8 +2832,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$t = $this->level->getTile($pos);
if($t instanceof Spawnable){
$nbt = new NBT(NBT::LITTLE_ENDIAN);
$nbt->read($packet->namedtag, false, true);
$nbt = new NetworkLittleEndianNBTStream();
$nbt->read($packet->namedtag);
$nbt = $nbt->getData();
if(!$t->updateCompoundTag($nbt, $this)){
$t->spawnTo($this);
@ -3357,7 +3323,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
$this->removeAllWindows(true);
$this->windows = null;
$this->windows = [];
$this->windowIndex = [];
$this->cursorInventory = null;
$this->craftingGrid = null;
@ -3568,6 +3534,10 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
break;
}
//Crafting grid must always be evacuated even if keep-inventory is true. This dumps the contents into the
//main inventory and drops the rest on the ground.
$this->resetCraftingGridType();
$this->server->getPluginManager()->callEvent($ev = new PlayerDeathEvent($this, $this->getDrops(), new TranslationContainer($message, $params)));
if(!$ev->getKeepInventory()){
@ -3579,6 +3549,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->inventory->setHeldItemIndex(0, false); //This is already handled when sending contents, don't send it twice
$this->inventory->clearAll();
}
if($this->armorInventory !== null){
$this->armorInventory->clearAll();
}
}
if($ev->getDeathMessage() != ""){
@ -3594,6 +3567,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return false; //never flag players for despawn
}
protected function applyPostDamageEffects(EntityDamageEvent $source) : void{
parent::applyPostDamageEffects($source);
$this->exhaust(0.3, PlayerExhaustEvent::CAUSE_DAMAGE);
}
public function attack(EntityDamageEvent $source){
if(!$this->isAlive()){
return;
@ -3609,13 +3588,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
parent::attack($source);
}
if($source->isCancelled()){
return;
}elseif($this->getLastDamageCause() === $source and $this->spawned){
protected function doHitAnimation() : void{
parent::doHitAnimation();
if($this->spawned){
$this->broadcastEntityEvent(EntityEventPacket::HURT_ANIMATION, null, [$this]);
$this->exhaust(0.3, PlayerExhaustEvent::CAUSE_DAMAGE);
}
}
@ -3688,6 +3666,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
protected function addDefaultWindows(){
$this->addWindow($this->getInventory(), ContainerIds::INVENTORY, true);
$this->addWindow($this->getArmorInventory(), ContainerIds::ARMOR, true);
$this->cursorInventory = new PlayerCursorInventory($this);
$this->addWindow($this->cursorInventory, ContainerIds::CURSOR, true);
@ -3735,13 +3715,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
* @return int
*/
public function getWindowId(Inventory $inventory) : int{
if($this->windows->contains($inventory)){
/** @var int $id */
$id = $this->windows[$inventory];
return $id;
}
return ContainerIds::NONE;
return $this->windows[spl_object_hash($inventory)] ?? ContainerIds::NONE;
}
/**
@ -3777,7 +3751,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$cnt = $forceId;
}
$this->windowIndex[$cnt] = $inventory;
$this->windows->attach($inventory, $cnt);
$this->windows[spl_object_hash($inventory)] = $cnt;
if($inventory->open($this)){
if($isPermanent){
$this->permanentWindows[$cnt] = true;
@ -3799,18 +3773,16 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
* @throws \BadMethodCallException if trying to remove a fixed inventory window without the `force` parameter as true
*/
public function removeWindow(Inventory $inventory, bool $force = false){
if($this->windows->contains($inventory)){
/** @var int $id */
$id = $this->windows[$inventory];
if(!$force and isset($this->permanentWindows[$id])){
throw new \BadMethodCallException("Cannot remove fixed window $id (" . get_class($inventory) . ") from " . $this->getName());
}
$this->windows->detach($this->windowIndex[$id]);
unset($this->windowIndex[$id]);
unset($this->permanentWindows[$id]);
$id = $this->windows[$hash = spl_object_hash($inventory)] ?? null;
if($id !== null and !$force and isset($this->permanentWindows[$id])){
throw new \BadMethodCallException("Cannot remove fixed window $id (" . get_class($inventory) . ") from " . $this->getName());
}
$inventory->close($this);
if($id !== null){
unset($this->windows[$hash], $this->windowIndex[$id], $this->permanentWindows[$id]);
}
}
/**
@ -3831,9 +3803,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
protected function sendAllInventories(){
foreach($this->windowIndex as $id => $inventory){
$inventory->sendContents($this);
if($inventory instanceof PlayerInventory){
$inventory->sendArmorContents($this);
}
}
}

View File

@ -81,7 +81,7 @@ namespace pocketmine {
const NAME = "PocketMine-MP";
const VERSION = "1.7dev";
const API_VERSION = "3.0.0-ALPHA10";
const API_VERSION = "3.0.0-ALPHA11";
const CODENAME = "[REDACTED]";
const MIN_PHP_VERSION = "7.2.0RC3";
@ -157,8 +157,6 @@ namespace pocketmine {
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
*/
$autoloader = new \BaseClassLoader();
$autoloader->addPath(\pocketmine\PATH . "src");
$autoloader->addPath(\pocketmine\PATH . "src" . DIRECTORY_SEPARATOR . "spl");
$autoloader->register(false);
set_time_limit(0); //Who set it to 30 seconds?!?!
@ -175,8 +173,8 @@ namespace pocketmine {
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-profiler"]);
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR);
define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : \getcwd() . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : \realpath(\getcwd()) . DIRECTORY_SEPARATOR);
define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : \realpath(\getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR);
Terminal::init();
@ -367,6 +365,10 @@ namespace pocketmine {
}
function kill($pid){
global $logger;
if($logger instanceof MainLogger){
$logger->syncFlushBuffer();
}
switch(Utils::getOS()){
case "win":
exec("taskkill.exe /F /PID " . ((int) $pid) . " > NUL");
@ -493,8 +495,9 @@ namespace pocketmine {
"curl" => "cURL",
"json" => "JSON",
"mbstring" => "Multibyte String",
"yaml" => "YAML",
"openssl" => "OpenSSL",
"sockets" => "Sockets",
"yaml" => "YAML",
"zip" => "Zip",
"zlib" => "Zlib"
];
@ -532,7 +535,6 @@ namespace pocketmine {
define('pocketmine\GIT_COMMIT', $gitHash);
@define("ENDIANNESS", (pack("d", 1) === "\77\360\0\0\0\0\0\0" ? Binary::BIG_ENDIAN : Binary::LITTLE_ENDIAN));
@define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1);
@ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors

View File

@ -67,6 +67,7 @@ use pocketmine\level\LevelException;
use pocketmine\metadata\EntityMetadataStore;
use pocketmine\metadata\LevelMetadataStore;
use pocketmine\metadata\PlayerMetadataStore;
use pocketmine\nbt\BigEndianNBTStream;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
@ -749,7 +750,7 @@ class Server{
if($this->shouldSavePlayerData()){
if(file_exists($path . "$name.dat")){
try{
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt = new BigEndianNBTStream();
$nbt->readCompressed(file_get_contents($path . "$name.dat"));
return $nbt->getData();
@ -772,8 +773,8 @@ class Server{
new DoubleTag("", $spawn->y),
new DoubleTag("", $spawn->z)
], NBT::TAG_Double),
new StringTag("Level", $this->getDefaultLevel()->getName()),
//new StringTag("SpawnLevel", $this->getDefaultLevel()->getName()),
new StringTag("Level", $this->getDefaultLevel()->getFolderName()),
//new StringTag("SpawnLevel", $this->getDefaultLevel()->getFolderName()),
//new IntTag("SpawnX", (int) $spawn->x),
//new IntTag("SpawnY", (int) $spawn->y),
//new IntTag("SpawnZ", (int) $spawn->z),
@ -815,7 +816,7 @@ class Server{
$this->pluginManager->callEvent($ev);
if(!$ev->isCancelled()){
$nbt = new NBT(NBT::BIG_ENDIAN);
$nbt = new BigEndianNBTStream();
try{
$nbt->setData($ev->getSaveData());
@ -1101,8 +1102,9 @@ class Server{
$this->getLogger()->notice($this->getLanguage()->translateString("pocketmine.level.backgroundGeneration", [$name]));
$centerX = $level->getSpawnLocation()->getX() >> 4;
$centerZ = $level->getSpawnLocation()->getZ() >> 4;
$spawnLocation = $level->getSpawnLocation();
$centerX = $spawnLocation->x >> 4;
$centerZ = $spawnLocation->z >> 4;
$order = [];
@ -1432,6 +1434,9 @@ class Server{
* @param string $pluginPath
*/
public function __construct(\ClassLoader $autoloader, \ThreadedLogger $logger, string $dataPath, string $pluginPath){
if(self::$instance !== null){
throw new \InvalidStateException("Only one server instance can exist at once");
}
self::$instance = $this;
self::$sleeper = new \Threaded;
$this->autoloader = $autoloader;
@ -1522,6 +1527,8 @@ class Server{
if($processors > 0){
$poolSize = max(1, $processors);
}
}else{
$poolSize = (int) $poolSize;
}
ServerScheduler::$WORKERS = $poolSize;
@ -1635,7 +1642,7 @@ class Server{
Attribute::init();
$this->craftingManager = new CraftingManager();
$this->resourceManager = new ResourcePackManager($this, $this->getDataPath() . "resource_packs" . DIRECTORY_SEPARATOR);
$this->resourceManager = new ResourcePackManager($this->getDataPath() . "resource_packs" . DIRECTORY_SEPARATOR);
$this->pluginManager = new PluginManager($this, $this->commandMap);
$this->pluginManager->subscribeToPermission(Server::BROADCAST_CHANNEL_ADMINISTRATIVE, $this->consoleSender);
@ -2089,11 +2096,13 @@ class Server{
if($this->network instanceof Network){
$this->getLogger()->debug("Stopping network interfaces");
foreach($this->network->getInterfaces() as $interface){
$this->getLogger()->debug("Stopping network interface " . get_class($interface));
$interface->shutdown();
$this->network->unregisterInterface($interface);
}
}
$this->getLogger()->debug("Collecting cycles");
gc_collect_cycles();
}catch(\Throwable $e){
$this->logger->logException($e);
@ -2113,7 +2122,7 @@ class Server{
/**
* Starts the PocketMine-MP server and starts processing ticks and packets
*/
public function start(){
private function start(){
if($this->getConfigBool("enable-query", true) === true){
$this->queryHandler = new QueryHandler();
}

View File

@ -30,6 +30,9 @@ abstract class Thread extends \Thread{
/** @var \ClassLoader */
protected $classLoader;
/** @var string|null */
protected $composerAutoloaderPath;
protected $isKilled = false;
public function getClassLoader(){
@ -37,6 +40,8 @@ abstract class Thread extends \Thread{
}
public function setClassLoader(\ClassLoader $loader = null){
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
if($loader === null){
$loader = Server::getInstance()->getLoader();
}
@ -51,10 +56,8 @@ abstract class Thread extends \Thread{
* (unless you are using a custom autoloader).
*/
public function registerClassLoader(){
require(\pocketmine\PATH . "vendor/autoload.php");
if(!interface_exists("ClassLoader", false)){
require(\pocketmine\PATH . "src/spl/ClassLoader.php");
require(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
if($this->composerAutoloaderPath !== null){
require $this->composerAutoloaderPath;
}
if($this->classLoader !== null){
$this->classLoader->register(false);

View File

@ -89,4 +89,4 @@ class ThreadManager extends \Volatile{
return $erroredThreads;
}
}
}

View File

@ -30,6 +30,8 @@ abstract class Worker extends \Worker{
/** @var \ClassLoader */
protected $classLoader;
/** @var string|null */
protected $composerAutoloaderPath;
protected $isKilled = false;
@ -38,6 +40,8 @@ abstract class Worker extends \Worker{
}
public function setClassLoader(\ClassLoader $loader = null){
$this->composerAutoloaderPath = \pocketmine\COMPOSER_AUTOLOADER_PATH;
if($loader === null){
$loader = Server::getInstance()->getLoader();
}
@ -52,10 +56,8 @@ abstract class Worker extends \Worker{
* (unless you are using a custom autoloader).
*/
public function registerClassLoader(){
require(\pocketmine\PATH . "vendor/autoload.php");
if(!interface_exists("ClassLoader", false)){
require(\pocketmine\PATH . "src/spl/ClassLoader.php");
require(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
if($this->composerAutoloaderPath !== null){
require $this->composerAutoloaderPath;
}
if($this->classLoader !== null){
$this->classLoader->register(false);

View File

@ -82,4 +82,4 @@ class Air extends Transparent{
return 0;
}
}
}

View File

@ -26,7 +26,7 @@ namespace pocketmine\block;
use pocketmine\inventory\AnvilInventory;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -65,7 +65,11 @@ class Anvil extends Fallable{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function recalculateBoundingBox() : ?AxisAlignedBB{
@ -106,13 +110,9 @@ class Anvil extends Fallable{
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return [
ItemFactory::get($this->getItemId(), $this->getDamage() & 0x0c, 1)
];
}
return [];
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get($this->getItemId(), $this->getDamage() & 0x0c)
];
}
}
}

View File

@ -190,25 +190,16 @@ class Bed extends Transparent{
return false;
}
public function onBreak(Item $item, Player $player = null) : bool{
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
if(($other = $this->getOtherHalf()) !== null){
$this->getLevel()->useBreakOn($other, $item, null, $player !== null); //make sure tiles get removed
}
return true;
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
if($this->isHeadPart()){
$tile = $this->getLevel()->getTile($this);
if($tile instanceof TileBed){
return [
ItemFactory::get($this->getItemId(), $tile->getColor(), 1)
ItemFactory::get($this->getItemId(), $tile->getColor())
];
}else{
return [
ItemFactory::get($this->getItemId(), 14, 1) //Red
ItemFactory::get($this->getItemId(), 14) //Red
];
}
}
@ -216,4 +207,15 @@ class Bed extends Transparent{
return [];
}
public function isAffectedBySilkTouch() : bool{
return false;
}
public function getAffectedBlocks() : array{
if(($other = $this->getOtherHalf()) !== null){
return [$this, $other];
}
return parent::getAffectedBlocks();
}
}

View File

@ -49,4 +49,4 @@ class Bedrock extends Solid{
return false;
}
}
}

View File

@ -38,20 +38,20 @@ class Beetroot extends Crops{
return "Beetroot Block";
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
if($this->meta >= 0x07){
return [
ItemFactory::get(Item::BEETROOT, 0, 1),
ItemFactory::get(Item::BEETROOT),
ItemFactory::get(Item::BEETROOT_SEEDS, 0, mt_rand(0, 3))
];
}
return [
ItemFactory::get(Item::BEETROOT_SEEDS, 0, 1)
ItemFactory::get(Item::BEETROOT_SEEDS)
];
}
public function getPickedItem() : Item{
return ItemFactory::get(Item::BEETROOT_SEEDS);
}
}
}

View File

@ -27,13 +27,13 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
use pocketmine\level\Level;
use pocketmine\level\MovingObjectPosition;
use pocketmine\level\Position;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\metadata\Metadatable;
use pocketmine\metadata\MetadataValue;
@ -195,8 +195,49 @@ class Block extends Position implements BlockIds, Metadatable{
return true;
}
public function canBeBrokenWith(Item $item) : bool{
return $this->getHardness() !== -1;
/**
* @return int
*/
public function getToolType() : int{
return BlockToolType::TYPE_NONE;
}
/**
* Returns the level of tool required to harvest this block (for normal blocks). When the tool type matches the
* block's required tool type, the tool must have a harvest level greater than or equal to this value to be able to
* successfully harvest the block.
*
* If the block requires a specific minimum tier of tiered tool, the minimum tier required should be returned.
* Otherwise, 1 should be returned if a tool is required, 0 if not.
*
* @see Item::getBlockToolHarvestLevel()
*
* @return int
*/
public function getToolHarvestLevel() : int{
return 0;
}
/**
* Returns whether the specified item is the proper tool to use for breaking this block. This checks tool type and
* harvest level requirement.
*
* In most cases this is also used to determine whether block drops should be created or not, except in some
* special cases such as vines.
*
* @param Item $tool
*
* @return bool
*/
public function isCompatibleWithTool(Item $tool) : bool{
if($this->getHardness() < 0){
return false;
}
$toolType = $this->getToolType();
$harvestLevel = $this->getToolHarvestLevel();
return $toolType === BlockToolType::TYPE_NONE or $harvestLevel === 0 or (
($toolType & $tool->getBlockToolType()) !== 0 and $tool->getBlockToolHarvestLevel() >= $harvestLevel);
}
/**
@ -220,41 +261,20 @@ class Block extends Position implements BlockIds, Metadatable{
* @return float
*/
public function getBreakTime(Item $item) : float{
$base = $this->getHardness() * 1.5;
if($this->canBeBrokenWith($item)){
if($this->getToolType() === Tool::TYPE_SHEARS and $item->isShears()){
$base /= 15;
}elseif(
($this->getToolType() === Tool::TYPE_PICKAXE and ($tier = $item->isPickaxe()) !== false) or
($this->getToolType() === Tool::TYPE_AXE and ($tier = $item->isAxe()) !== false) or
($this->getToolType() === Tool::TYPE_SHOVEL and ($tier = $item->isShovel()) !== false)
){
switch($tier){
case Tool::TIER_WOODEN:
$base /= 2;
break;
case Tool::TIER_STONE:
$base /= 4;
break;
case Tool::TIER_IRON:
$base /= 6;
break;
case Tool::TIER_DIAMOND:
$base /= 8;
break;
case Tool::TIER_GOLD:
$base /= 12;
break;
}
}
$base = $this->getHardness();
if($this->isCompatibleWithTool($item)){
$base *= 1.5;
}else{
$base *= 3.33;
$base *= 5;
}
if($item->isSword()){
$base /= 1.5;
$efficiency = $item->getMiningEfficiency($this);
if($efficiency <= 0){
throw new \RuntimeException("Item efficiency is invalid");
}
$base /= $efficiency;
return $base;
}
@ -315,13 +335,6 @@ class Block extends Position implements BlockIds, Metadatable{
return $this->getHardness() * 5;
}
/**
* @return int
*/
public function getToolType() : int{
return Tool::TYPE_NONE;
}
/**
* @return float
*/
@ -420,11 +433,53 @@ class Block extends Position implements BlockIds, Metadatable{
* @return Item[]
*/
public function getDrops(Item $item) : array{
if($this->isCompatibleWithTool($item)){
if($this->isAffectedBySilkTouch() and $item->hasEnchantment(Enchantment::SILK_TOUCH)){
return $this->getSilkTouchDrops($item);
}
return $this->getDropsForCompatibleTool($item);
}
return [];
}
/**
* Returns an array of Items to be dropped when the block is broken using the correct tool type.
*
* @param Item $item
*
* @return Item[]
*/
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get($this->getItemId(), $this->getVariant(), 1)
ItemFactory::get($this->getItemId(), $this->getVariant())
];
}
/**
* Returns an array of Items to be dropped when the block is broken using a compatible Silk Touch-enchanted tool.
*
* @param Item $item
*
* @return Item[]
*/
public function getSilkTouchDrops(Item $item) : array{
return [
ItemFactory::get($this->getItemId(), $this->getVariant())
];
}
/**
* Returns whether Silk Touch enchanted tools will cause this block to drop as itself. Since most blocks drop
* themselves anyway, this is implicitly true.
*
* @return bool
*/
public function isAffectedBySilkTouch() : bool{
return true;
}
/**
* Returns the item that players will equip when middle-clicking on this block.
* @return Item
@ -486,6 +541,16 @@ class Block extends Position implements BlockIds, Metadatable{
);
}
/**
* Returns a list of blocks that this block is part of. In most cases, only contains the block itself, but in cases
* such as double plants, beds and doors, will contain both halves.
*
* @return Block[]
*/
public function getAffectedBlocks() : array{
return [$this];
}
/**
* @return string
*/
@ -578,15 +643,15 @@ class Block extends Position implements BlockIds, Metadatable{
* @param Vector3 $pos1
* @param Vector3 $pos2
*
* @return MovingObjectPosition|null
* @return RayTraceResult|null
*/
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?MovingObjectPosition{
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
$bbs = $this->getCollisionBoxes();
if(empty($bbs)){
return null;
}
/** @var MovingObjectPosition|null $currentHit */
/** @var RayTraceResult|null $currentHit */
$currentHit = null;
/** @var int|float $currentDistance */
$currentDistance = PHP_INT_MAX;
@ -604,12 +669,6 @@ class Block extends Position implements BlockIds, Metadatable{
}
}
if($currentHit !== null){
$currentHit->blockX = $this->x;
$currentHit->blockY = $this->y;
$currentHit->blockZ = $this->z;
}
return $currentHit;
}

View File

@ -417,4 +417,4 @@ class BlockFactory{
$b = self::$list[$id];
return $b !== null and !($b instanceof UnknownBlock);
}
}
}

View File

@ -21,19 +21,19 @@
declare(strict_types=1);
namespace pocketmine\item;
namespace pocketmine\block;
/**
* Types of tools that can be used to break blocks
* Blocks may allow multiple tool types by combining these bitflags
*/
interface BlockToolType{
class DiamondPickaxe extends Tool{
public function __construct(int $meta = 0){
parent::__construct(self::DIAMOND_PICKAXE, $meta, "Diamond Pickaxe");
}
public const TYPE_NONE = 0;
public const TYPE_SWORD = 1 << 0;
public const TYPE_SHOVEL = 1 << 1;
public const TYPE_PICKAXE = 1 << 2;
public const TYPE_AXE = 1 << 3;
public const TYPE_SHEARS = 1 << 4;
public function isPickaxe(){
return Tool::TIER_DIAMOND;
}
public function getAttackPoints() : int{
return 6;
}
}

View File

@ -25,7 +25,7 @@ namespace pocketmine\block;
use pocketmine\block\utils\PillarRotationHelper;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -46,7 +46,11 @@ class BoneBlock extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
@ -57,13 +61,4 @@ class BoneBlock extends Solid{
public function getVariantBitmask() : int{
return 0x03;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return parent::getDrops($item);
}
return [];
}
}
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
class Bookshelf extends Solid{
@ -44,10 +43,10 @@ class Bookshelf extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_AXE;
return BlockToolType::TYPE_AXE;
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::BOOK, 0, 3)
];
@ -57,4 +56,4 @@ class Bookshelf extends Solid{
return 300;
}
}
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class BrewingStand extends Transparent{
@ -42,7 +42,11 @@ class BrewingStand extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getVariantBitmask() : int{
@ -50,4 +54,4 @@ class BrewingStand extends Transparent{
}
//TODO
}
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class BrickStairs extends Stair{
@ -42,11 +42,15 @@ class BrickStairs extends Stair{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getName() : string{
return "Brick Stairs";
}
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class Bricks extends Solid{
@ -43,18 +42,14 @@ class Bricks extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getName() : string{
return "Bricks";
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return parent::getDrops($item);
}
return [];
}
}
}

View File

@ -34,4 +34,4 @@ class BrownMushroom extends RedMushroom{
public function getLightLevel() : int{
return 1;
}
}
}

View File

@ -33,9 +33,9 @@ class BrownMushroomBlock extends RedMushroomBlock{
return "Brown Mushroom Block";
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [
Item::get(Item::BROWN_MUSHROOM, 0, mt_rand(0, 2))
];
}
}
}

View File

@ -24,7 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\StringTag;
use pocketmine\Player;
@ -35,6 +35,8 @@ class BurningFurnace extends Solid{
protected $id = self::BURNING_FURNACE;
protected $itemId = self::FURNACE;
public function __construct(int $meta = 0){
$this->meta = $meta;
}
@ -48,7 +50,11 @@ class BurningFurnace extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getLightLevel() : int{
@ -90,12 +96,4 @@ class BurningFurnace extends Solid{
public function getVariantBitmask() : int{
return 0;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return parent::getDrops($item);
}
return [];
}
}
}

View File

@ -48,4 +48,4 @@ abstract class Button extends Flowable{
//TODO
return true;
}
}
}

View File

@ -132,4 +132,4 @@ class Cactus extends Transparent{
public function getVariantBitmask() : int{
return 0;
}
}
}

View File

@ -24,7 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Effect;
use pocketmine\event\entity\EntityEatBlockEvent;
use pocketmine\entity\Living;
use pocketmine\item\FoodSource;
use pocketmine\item\Item;
use pocketmine\level\Level;
@ -45,7 +45,7 @@ class Cake extends Transparent implements FoodSource{
}
public function getName() : string{
return "Cake Block";
return "Cake";
}
protected function recalculateBoundingBox() : ?AxisAlignedBB{
@ -85,25 +85,18 @@ class Cake extends Transparent implements FoodSource{
return false;
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [];
}
public function isAffectedBySilkTouch() : bool{
return false;
}
public function onActivate(Item $item, Player $player = null) : bool{
//TODO: refactor this into generic food handling
if($player instanceof Player and $player->getFood() < $player->getMaxFood()){
$player->getServer()->getPluginManager()->callEvent($ev = new EntityEatBlockEvent($player, $this));
if(!$ev->isCancelled()){
$player->addFood($ev->getFoodRestore());
$player->addSaturation($ev->getSaturationRestore());
foreach($ev->getAdditionalEffects() as $effect){
$player->addEffect($effect);
}
$this->getLevel()->setBlock($this, $ev->getResidue());
return true;
}
if($player !== null){
$player->consumeObject($this);
return true;
}
return false;
@ -117,6 +110,13 @@ class Cake extends Transparent implements FoodSource{
return 0.4;
}
public function requiresHunger() : bool{
return true;
}
/**
* @return Block
*/
public function getResidue(){
$clone = clone $this;
$clone->meta++;
@ -132,4 +132,8 @@ class Cake extends Transparent implements FoodSource{
public function getAdditionalEffects() : array{
return [];
}
public function onConsume(Living $consumer) : void{
$this->level->setBlock($this, $this->getResidue());
}
}

View File

@ -85,4 +85,4 @@ class Carpet extends Flowable{
return false;
}
}
}

View File

@ -38,7 +38,7 @@ class Carrot extends Crops{
return "Carrot Block";
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::CARROT, 0, $this->meta >= 0x07 ? mt_rand(1, 4) : 1)
];
@ -47,4 +47,4 @@ class Carrot extends Crops{
public function getPickedItem() : Item{
return ItemFactory::get(Item::CARROT);
}
}
}

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\StringTag;
@ -49,7 +48,7 @@ class Chest extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_AXE;
return BlockToolType::TYPE_AXE;
}
protected function recalculateBoundingBox() : ?AxisAlignedBB{
@ -102,16 +101,6 @@ class Chest extends Transparent{
return true;
}
public function onBreak(Item $item, Player $player = null) : bool{
$t = $this->getLevel()->getTile($this);
if($t instanceof TileChest){
$t->unpair();
}
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
return true;
}
public function onActivate(Item $item, Player $player = null) : bool{
if($player instanceof Player){
@ -144,4 +133,4 @@ class Chest extends Transparent{
public function getFuelTime() : int{
return 300;
}
}
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
class Clay extends Solid{
@ -40,16 +39,16 @@ class Clay extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_SHOVEL;
return BlockToolType::TYPE_SHOVEL;
}
public function getName() : string{
return "Clay Block";
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::CLAY_BALL, 0, 4)
];
}
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class Coal extends Solid{
@ -39,22 +38,18 @@ class Coal extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getName() : string{
return "Coal Block";
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return parent::getDrops($item);
}
return [];
}
public function getFuelTime() : int{
return 16000;
}
}
}

View File

@ -25,7 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class CoalOre extends Solid{
@ -40,21 +40,21 @@ class CoalOre extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getName() : string{
return "Coal Ore";
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return [
ItemFactory::get(Item::COAL, 0, 1)
];
}
return [];
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::COAL)
];
}
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class Cobblestone extends Solid{
@ -35,7 +34,11 @@ class Cobblestone extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getName() : string{
@ -45,12 +48,4 @@ class Cobblestone extends Solid{
public function getHardness() : float{
return 2;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return parent::getDrops($item);
}
return [];
}
}
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class CobblestoneStairs extends Stair{
@ -38,11 +38,15 @@ class CobblestoneStairs extends Stair{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getName() : string{
return "Cobblestone Stairs";
}
}
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
@ -38,7 +38,11 @@ class CobblestoneWall extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getHardness() : float{

View File

@ -25,7 +25,7 @@ namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\ItemFactory;
class Cobweb extends Flowable{
@ -48,19 +48,24 @@ class Cobweb extends Flowable{
}
public function getToolType() : int{
return Tool::TYPE_SWORD;
return BlockToolType::TYPE_SWORD | BlockToolType::TYPE_SHEARS;
}
public function getToolHarvestLevel() : int{
return 1;
}
public function onEntityCollide(Entity $entity) : void{
$entity->resetFallDistance();
}
public function getDrops(Item $item) : array{
//TODO: correct drops
return [];
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::STRING)
];
}
public function diffusesSkyLight() : bool{
return true;
}
}
}

View File

@ -35,5 +35,17 @@ class CocoaBlock extends Transparent{
return "Cocoa Block";
}
public function getHardness() : float{
return 0.2;
}
public function getToolType() : int{
return BlockToolType::TYPE_AXE;
}
//TODO
public function isAffectedBySilkTouch() : bool{
return false;
}
}

View File

@ -24,8 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColorBlockMetaHelper;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class Concrete extends Solid{
@ -44,15 +43,10 @@ class Concrete extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return parent::getDrops($item);
}
return [];
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
}
}

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColorBlockMetaHelper;
use pocketmine\item\Tool;
use pocketmine\level\Level;
class ConcretePowder extends Fallable{
@ -44,7 +43,7 @@ class ConcretePowder extends Fallable{
}
public function getToolType() : int{
return Tool::TYPE_SHOVEL;
return BlockToolType::TYPE_SHOVEL;
}
public function onUpdate(int $type){
@ -75,4 +74,4 @@ class ConcretePowder extends Fallable{
return null;
}
}
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\inventory\BigCraftingGrid;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\Player;
class CraftingTable extends Solid{
@ -45,7 +44,7 @@ class CraftingTable extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_AXE;
return BlockToolType::TYPE_AXE;
}
public function onActivate(Item $item, Player $player = null) : bool{
@ -59,4 +58,4 @@ class CraftingTable extends Solid{
public function getFuelTime() : int{
return 300;
}
}
}

View File

@ -95,4 +95,8 @@ abstract class Crops extends Flowable{
return false;
}
}
public function isAffectedBySilkTouch() : bool{
return false;
}
}

View File

@ -63,4 +63,4 @@ class Dandelion extends Flowable{
return false;
}
}
}

View File

@ -43,5 +43,9 @@ class DaylightSensor extends Transparent{
return 300;
}
public function getToolType() : int{
return BlockToolType::TYPE_AXE;
}
//TODO
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
@ -54,16 +53,20 @@ class DeadBush extends Flowable{
}
public function getToolType() : int{
return Tool::TYPE_SHEARS;
return BlockToolType::TYPE_SHEARS;
}
public function getToolHarvestLevel() : int{
return 1;
}
public function getDrops(Item $item) : array{
if($item->isShears()){
return parent::getDrops($item);
if(!$this->isCompatibleWithTool($item)){
return [
ItemFactory::get(Item::STICK, 0, mt_rand(0, 2))
];
}
return [
ItemFactory::get(Item::STICK, 0, mt_rand(0, 2))
];
return parent::getDrops($item);
}
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class Diamond extends Solid{
@ -43,14 +42,10 @@ class Diamond extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_IRON){
return parent::getDrops($item);
}
return [];
public function getToolHarvestLevel() : int{
return TieredTool::TIER_IRON;
}
}
}

View File

@ -25,7 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class DiamondOre extends Solid{
@ -44,16 +44,16 @@ class DiamondOre extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_IRON){
return [
ItemFactory::get(Item::DIAMOND, 0, 1)
];
}
return [];
public function getToolHarvestLevel() : int{
return TieredTool::TIER_IRON;
}
}
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::DIAMOND)
];
}
}

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\Player;
class Dirt extends Solid{
@ -40,7 +39,7 @@ class Dirt extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_SHOVEL;
return BlockToolType::TYPE_SHOVEL;
}
public function getName() : string{
@ -64,4 +63,4 @@ class Dirt extends Solid{
return false;
}
}
}

View File

@ -246,23 +246,6 @@ abstract class Door extends Transparent{
return false;
}
public function onBreak(Item $item, Player $player = null) : bool{
if(($this->getDamage() & 0x08) === 0x08){
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === $this->getId()){
$this->getLevel()->setBlock($down, BlockFactory::get(Block::AIR), true);
}
}else{
$up = $this->getSide(Vector3::SIDE_UP);
if($up->getId() === $this->getId()){
$this->getLevel()->setBlock($up, BlockFactory::get(Block::AIR), true);
}
}
$this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true);
return true;
}
public function onActivate(Item $item, Player $player = null) : bool{
if(($this->getDamage() & 0x08) === 0x08){ //Top
$down = $this->getSide(Vector3::SIDE_DOWN);
@ -286,4 +269,32 @@ abstract class Door extends Transparent{
public function getVariantBitmask() : int{
return 0;
}
}
public function getDropsForCompatibleTool(Item $item) : array{
if(($this->meta & 0x08) === 0){ //bottom half only
return parent::getDropsForCompatibleTool($item);
}
return [];
}
public function isAffectedBySilkTouch() : bool{
return false;
}
public function getAffectedBlocks() : array{
if(($this->getDamage() & 0x08) === 0x08){
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === $this->getId()){
return [$this, $down];
}
}else{
$up = $this->getSide(Vector3::SIDE_UP);
if($up->getId() === $this->getId()){
return [$this, $up];
}
}
return parent::getAffectedBlocks();
}
}

View File

@ -97,33 +97,39 @@ class DoublePlant extends Flowable{
return false;
}
public function onBreak(Item $item, Player $player = null) : bool{
if(parent::onBreak($item, $player) and $this->isValidHalfPlant()){
$this->getLevel()->useBreakOn($this->getSide(($this->meta & self::BITFLAG_TOP) !== 0 ? Vector3::SIDE_DOWN : Vector3::SIDE_UP), $item, $player, $player !== null);
}
return false;
}
public function getVariantBitmask() : int{
return 0x07;
}
public function getToolType() : int{
return ($this->meta === 2 or $this->meta === 3) ? BlockToolType::TYPE_SHEARS : BlockToolType::TYPE_NONE;
}
public function getToolHarvestLevel() : int{
return ($this->meta === 2 or $this->meta === 3) ? 1 : 0; //only grass or fern require shears
}
public function getDrops(Item $item) : array{
if($this->meta & self::BITFLAG_TOP){
if(!$item->isShears() and ($this->meta === 2 or $this->meta === 3)){ //grass or fern
if(mt_rand(0, 24) === 0){
return [
ItemFactory::get(Item::SEEDS, 0, 1)
];
}
return [];
if($this->isCompatibleWithTool($item)){
return parent::getDrops($item);
}
return parent::getDrops($item);
if(mt_rand(0, 24) === 0){
return [
ItemFactory::get(Item::SEEDS)
];
}
}
return [];
}
}
public function getAffectedBlocks() : array{
if($this->isValidHalfPlant()){
return [$this, $this->getSide(($this->meta & self::BITFLAG_TOP) !== 0 ? Vector3::SIDE_DOWN : Vector3::SIDE_UP)];
}
return parent::getAffectedBlocks();
}
}

View File

@ -38,10 +38,13 @@ abstract class DoubleSlab extends Solid{
return "Double " . BlockFactory::get($this->getSlabId(), $this->getVariant())->getName() . " Slab";
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get($this->getSlabId(), $this->getVariant(), 2)
];
}
}
public function isAffectedBySilkTouch() : bool{
return false;
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class DoubleStoneSlab extends DoubleSlab{
@ -39,15 +38,10 @@ class DoubleStoneSlab extends DoubleSlab{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return parent::getDrops($item);
}
return [];
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
}
}

View File

@ -31,4 +31,4 @@ class DoubleStoneSlab2 extends DoubleStoneSlab{
return self::STONE_SLAB2;
}
}
}

View File

@ -23,8 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
class DoubleWoodenSlab extends DoubleSlab{
protected $id = self::DOUBLE_WOODEN_SLAB;
@ -38,6 +36,6 @@ class DoubleWoodenSlab extends DoubleSlab{
}
public function getToolType() : int{
return Tool::TYPE_AXE;
return BlockToolType::TYPE_AXE;
}
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class Emerald extends Solid{
@ -39,18 +38,14 @@ class Emerald extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_IRON;
}
public function getName() : string{
return "Emerald Block";
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_IRON){
return parent::getDrops($item);
}
return [];
}
}
}

View File

@ -25,7 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class EmeraldOre extends Solid{
@ -40,20 +40,20 @@ class EmeraldOre extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_IRON;
}
public function getHardness() : float{
return 3;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_IRON){
return [
ItemFactory::get(Item::EMERALD, 0, 1)
];
}
return [];
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::EMERALD)
];
}
}
}

View File

@ -25,7 +25,7 @@ namespace pocketmine\block;
use pocketmine\inventory\EnchantInventory;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\tile\EnchantTable as TileEnchantTable;
@ -60,7 +60,11 @@ class EnchantingTable extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function onActivate(Item $item, Player $player = null) : bool{
@ -72,12 +76,4 @@ class EnchantingTable extends Transparent{
return true;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return parent::getDrops($item);
}
return [];
}
}
}

View File

@ -65,4 +65,4 @@ class EndPortalFrame extends Solid{
$this->z + 1
);
}
}
}

View File

@ -101,4 +101,4 @@ class EndRod extends Flowable{
public function getVariantBitmask() : int{
return 0;
}
}
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class EndStone extends Solid{
@ -38,10 +38,14 @@ class EndStone extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getHardness() : float{
return 3;
}
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class EndStoneBricks extends Solid{
@ -43,15 +42,10 @@ class EndStoneBricks extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return parent::getDrops($item);
}
return [];
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
}
}

View File

@ -25,7 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\tile\EnderChest as TileEnderChest;
@ -52,7 +52,11 @@ class EnderChest extends Chest{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
@ -71,10 +75,6 @@ class EnderChest extends Chest{
return true;
}
public function onBreak(Item $item, Player $player = null) : bool{
return Block::onBreak($item, $player);
}
public function onActivate(Item $item, Player $player = null) : bool{
if($player instanceof Player){
@ -97,16 +97,14 @@ class EnderChest extends Chest{
return true;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return [ItemFactory::get(Item::OBSIDIAN, 0, 8)];
}
return [];
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::OBSIDIAN, 0, 8)
];
}
public function getFuelTime() : int{
return 0;
}
}
}

View File

@ -54,4 +54,4 @@ abstract class Fallable extends Solid{
public function tickFalling() : ?Block{
return null;
}
}
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
@ -47,7 +46,7 @@ class Farmland extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_SHOVEL;
return BlockToolType::TYPE_SHOVEL;
}
public function ticksRandomly() : bool{
@ -108,9 +107,13 @@ class Farmland extends Transparent{
return false;
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::DIRT, 0, 1)
ItemFactory::get(Item::DIRT)
];
}
}
public function isAffectedBySilkTouch() : bool{
return false;
}
}

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\level\sound\DoorSound;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
@ -37,7 +36,7 @@ class FenceGate extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_AXE;
return BlockToolType::TYPE_AXE;
}

View File

@ -79,7 +79,7 @@ class Fire extends Flowable{
}
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [];
}
@ -114,4 +114,4 @@ class Fire extends Flowable{
return false;
}
}
}

View File

@ -42,4 +42,4 @@ abstract class Flowable extends Transparent{
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return null;
}
}
}

View File

@ -82,4 +82,4 @@ class Flower extends Flowable{
return false;
}
}
}

View File

@ -96,8 +96,12 @@ class FlowerPot extends Flowable{
return true;
}
public function getDrops(Item $item) : array{
$items = parent::getDrops($item);
public function getVariantBitmask() : int{
return 0;
}
public function getDropsForCompatibleTool(Item $item) : array{
$items = parent::getDropsForCompatibleTool($item);
$tile = $this->getLevel()->getTile($this);
if($tile instanceof TileFlowerPot){
@ -110,4 +114,7 @@ class FlowerPot extends Flowable{
return $items;
}
}
public function isAffectedBySilkTouch() : bool{
return false;
}
}

View File

@ -35,4 +35,4 @@ class Furnace extends BurningFurnace{
public function getLightLevel() : int{
return 0;
}
}
}

View File

@ -41,7 +41,7 @@ class Glass extends Transparent{
return 0.3;
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [];
}
}
}

View File

@ -41,7 +41,7 @@ class GlassPane extends Thin{
return 0.3;
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [];
}
}
}

View File

@ -25,7 +25,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -36,7 +36,11 @@ class GlazedTerracotta extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
@ -56,12 +60,4 @@ class GlazedTerracotta extends Solid{
public function getVariantBitmask() : int{
return 0;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return parent::getDrops($item);
}
return [];
}
}
}

View File

@ -24,6 +24,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\TieredTool;
class GlowingObsidian extends Solid{
protected $id = self::GLOWING_OBSIDIAN;
@ -47,4 +49,12 @@ class GlowingObsidian extends Solid{
public function getBlastResistance() : float{
return 50;
}
}
public function getToolType() : int{
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_DIAMOND;
}
}

View File

@ -29,6 +29,8 @@ class GlowingRedstoneOre extends RedstoneOre{
protected $id = self::GLOWING_REDSTONE_ORE;
protected $itemId = self::REDSTONE_ORE;
public function getName() : string{
return "Glowing Redstone Ore";
}
@ -46,4 +48,4 @@ class GlowingRedstoneOre extends RedstoneOre{
return false;
}
}
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
class Glowstone extends Transparent{
@ -44,16 +43,16 @@ class Glowstone extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getLightLevel() : int{
return 15;
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::GLOWSTONE_DUST, 0, mt_rand(2, 4))
];
}
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class Gold extends Solid{
@ -43,14 +42,10 @@ class Gold extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_IRON){
return parent::getDrops($item);
}
return [];
public function getToolHarvestLevel() : int{
return TieredTool::TIER_IRON;
}
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class GoldOre extends Solid{
@ -43,14 +42,10 @@ class GoldOre extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_IRON){
return parent::getDrops($item);
}
return [];
public function getToolHarvestLevel() : int{
return TieredTool::TIER_IRON;
}
}
}

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
use pocketmine\level\generator\object\TallGrass as TallGrassObject;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
@ -50,12 +49,12 @@ class Grass extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_SHOVEL;
return BlockToolType::TYPE_SHOVEL;
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::DIRT, 0, 1)
ItemFactory::get(Item::DIRT)
];
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
@ -43,7 +42,7 @@ class GrassPath extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_SHOVEL;
return BlockToolType::TYPE_SHOVEL;
}
protected function recalculateBoundingBox() : ?AxisAlignedBB{
@ -70,9 +69,9 @@ class GrassPath extends Transparent{
return false;
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::DIRT, 0, 1)
ItemFactory::get(Item::DIRT)
];
}
}
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
class Gravel extends Fallable{
@ -44,17 +43,17 @@ class Gravel extends Fallable{
}
public function getToolType() : int{
return Tool::TYPE_SHOVEL;
return BlockToolType::TYPE_SHOVEL;
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
if(mt_rand(1, 10) === 1){
return [
ItemFactory::get(Item::FLINT, 0, 1)
ItemFactory::get(Item::FLINT)
];
}
return parent::getDrops($item);
return parent::getDropsForCompatibleTool($item);
}
}
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class HardenedClay extends Solid{
@ -38,10 +38,14 @@ class HardenedClay extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getHardness() : float{
return 1.25;
}
}
}

View File

@ -54,4 +54,4 @@ class HayBale extends Solid{
public function getVariantBitmask() : int{
return 0x03;
}
}
}

View File

@ -23,8 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\level\Level;
use pocketmine\Player;
@ -53,11 +53,14 @@ class Ice extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function onBreak(Item $item, Player $player = null) : bool{
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::WATER), true);
if(!$item->hasEnchantment(Enchantment::SILK_TOUCH)){
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::WATER), true);
}
return parent::onBreak($item, $player);
}
public function ticksRandomly() : bool{
@ -75,7 +78,7 @@ class Ice extends Transparent{
return false;
}
public function getDrops(Item $item) : array{
public function getDropsForCompatibleTool(Item $item) : array{
return [];
}
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class Iron extends Solid{
@ -39,18 +38,14 @@ class Iron extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_STONE;
}
public function getHardness() : float{
return 5;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_STONE){
return parent::getDrops($item);
}
return [];
}
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class IronBars extends Thin{
@ -43,20 +42,15 @@ class IronBars extends Thin{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getVariantBitmask() : int{
return 0;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return parent::getDrops($item);
}
return [];
}
}

View File

@ -24,7 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class IronDoor extends Door{
@ -41,18 +41,14 @@ class IronDoor extends Door{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getHardness() : float{
return 5;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return parent::getDrops($item);
}
return [];
}
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class IronOre extends Solid{
@ -39,18 +38,14 @@ class IronOre extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_STONE;
}
public function getHardness() : float{
return 3;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_STONE){
return parent::getDrops($item);
}
return [];
}
}
}

View File

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class IronTrapdoor extends Trapdoor{
@ -38,6 +38,10 @@ class IronTrapdoor extends Trapdoor{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
}

View File

@ -99,8 +99,8 @@ class ItemFrame extends Flowable{
return 0;
}
public function getDrops(Item $item) : array{
$drops = parent::getDrops($item);
public function getDropsForCompatibleTool(Item $item) : array{
$drops = parent::getDropsForCompatibleTool($item);
$tile = $this->level->getTile($this);
if($tile instanceof TileItemFrame){
@ -112,4 +112,8 @@ class ItemFrame extends Flowable{
return $drops;
}
}
public function isAffectedBySilkTouch() : bool{
return false;
}
}

View File

@ -25,7 +25,6 @@ namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
@ -122,10 +121,10 @@ class Ladder extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_AXE;
return BlockToolType::TYPE_AXE;
}
public function getVariantBitmask() : int{
return 0;
}
}
}

View File

@ -23,8 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class Lapis extends Solid{
@ -39,19 +38,14 @@ class Lapis extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_STONE;
}
public function getHardness() : float{
return 3;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_STONE){
return parent::getDrops($item);
}
return [];
}
}
}

View File

@ -25,7 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class LapisOre extends Solid{
@ -40,21 +40,21 @@ class LapisOre extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_STONE;
}
public function getName() : string{
return "Lapis Lazuli Ore";
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_STONE){
return [
ItemFactory::get(Item::DYE, 4, mt_rand(4, 8))
];
}
return [];
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::DYE, 4, mt_rand(4, 8))
];
}
}
}

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