Compare commits

..

976 Commits

Author SHA1 Message Date
a3fa8adf4a Fixed XP orbs trying to track players after teleport
closes #2028

@mal0ne-23, you are today's MVP.
2018-02-17 10:58:54 +00:00
cacd0f5d8f Level: fixed global packet mechanism spamming empty batch packets every tick
This also spammed to nobody when the level is empty.

Closes #2020.
2018-02-14 09:12:07 +00:00
3600542d78 Timings: fixed pastes not working after ubuntu pastebin update 2018-02-11 09:55:52 +00:00
e0ed877494 Protocol changes for 1.2.10 release
Looks like they reverted near enough everything they did in the beta.
2018-02-08 11:19:04 +00:00
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
66562f24fb Made Leaves drops more generic, fix dark oak leaves not dropping apples 2017-12-13 12:57:58 +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
dc064dfa2e Level: Fixed some unnecessary double uses of Level::blockHash() 2017-12-13 11:25:36 +00:00
131a6a4d19 Cache fix related to #1813: Don't cache blocks for chunks that don't exist 2017-12-13 10:47:12 +00:00
67a576722c Fixed item frames placed on invalid blocks, close #1804 2017-12-13 09:46:18 +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
3beccc47cd SlotChangeAction: Remove superfluous >= 0 inventorySlot check
This is done by slotExists() anyway.
2017-12-12 10:36:53 +00:00
dfc2d1dfe6 Stop hardcoding src/pocketmine/resources everywhere 2017-12-11 19:52:49 +00:00
1f1531810d Added \pocketmine\RESOURCE_PATH and Server->getResourcePath() 2017-12-11 19:52:20 +00:00
a5fc77749f Added -file (-f) option to start.ps1
This allows specifying a PocketMine-MP PHP file to execute (phar or source) to use to run the server, like start.sh. If not specified, auto-detection is used.
2017-12-11 19:40:02 +00:00
98cb7f2e10 Removed redundant filePath from Server constructor
This parameter is hardcoded to \pocketmine\PATH in PocketMine.php. Additionally, it does not make sense for the server source path to not be the server source path. \pocketmine\PATH is accessible from the Server context, therefore it should be used and does not need to be stored.
2017-12-11 19:25:06 +00:00
e58db75396 Level: Remove redundant null checks from useBreakOn()
These checks are not needed as of 3eae7a1875.
2017-12-11 16:31:43 +00:00
a94c669730 Fixed sword efficiency on anything that's not cobwebs 2017-12-11 12:57:18 +00:00
45ee115b67 Player: Fixed bad effects killing creative players
Players aren't supposed to take magic damage in creative... I don't know who added this, but it's wrong.
2017-12-10 20:50:50 +00:00
44e06f6a32 Player: Stop abusing getItemInHand() when we already have it stored 2017-12-10 17:08:56 +00:00
2e62c084a4 Oops! composer.lock wasn't up to date 2017-12-10 12:34:01 +00:00
a3622dfa9d Updated PocketMine-SPL dependency 2017-12-10 12:26:48 +00:00
7c8a29151c MemoryManager: Remove unused field (leftover from 59d9d6a7df) 2017-12-10 12:12:43 +00:00
8a90d159fe Cleanup unused imports 2017-12-10 12:09:46 +00:00
bf4076766e Living: Fixed passing FloatTag to setHealth() when HealF tag is present, close #1784 2017-12-09 20:31:14 +00:00
49dbd8b2c8 Living: Remove superfluous fire resistance check from dealFireDamage()
This is already checked in Living->attack(). It's preferable to allow it to be cancelled there since plugins can then un-cancel EntityDamageEvent to bypass the effect.
2017-12-07 17:32:50 +00:00
502dd14c67 Entity: Remove excess whitespace in doOnFireTick() 2017-12-07 17:28:37 +00:00
74239eec69 Living: Remove nonsensical >0 condition on boolean
Maybe this once returned integers, but it doesn't anymore.
2017-12-07 16:49:16 +00:00
3c936e1be8 Entity: removed dead maxFireTicks property 2017-12-07 16:37:32 +00:00
16fd37a039 Entity: Add getter & setter for fireTicks 2017-12-07 16:37:01 +00:00
1ce961f688 Merge branch 'command-reader-fix' 2017-12-07 13:55:48 +00:00
d80f711d18 CommandReader: Removed redundant else branch 2017-12-07 13:50:24 +00:00
ebd3d207e4 Fixed server not accepting commands after pressing ctrl+D (non-readline) 2017-12-07 13:42:34 +00:00
31f0437c96 fix readline crash when user presses ctrl+D 2017-12-07 13:41:58 +00:00
b06ca6eb0b Rename Living->callDeathEvent() to Living->onDeath() 2017-12-07 12:26:49 +00:00
67a09a9b16 Bump versions for 1.2.6
No changes. Mojang sucks.
2017-12-06 18:12:45 +00:00
51cec525ee Added methods for calculating sun angle and sky light level reduction by day time
Use real sky light level in Level->getFullLightAt()

close #1471
2017-12-06 12:40:52 +00:00
a5f4dda918 Added documentation for Level->addChunkPacket()
this method is confusingly named
2017-12-06 11:15:17 +00:00
e2d66ac96d Use Player->isBanned() instead of repeating code 2017-12-06 10:38:02 +00:00
d03fdd5f72 Liquids refactor, bug fixes and performance improvements (#1753)
* Added Liquid->getLiquidLevelDecreasePerBlock()

* Fixed lava turning into cobblestone when flowing over water

* Cache liquid flow vectors for faster entity movement

* Removed a condition that made lava impossible to get rid of
In the PC code, the equivalent code makes the delay between scheduled ticks 4 times longer. Here, it just breaks the code. I don't know what the 4x stuff is about, but this code does not produce the expected behaviour and lava works fine regardless.

* Fixed strange behaviour with liquids trying to flow into other liquids
Liquids should consider other liquids as a path of least resistance. However, they should not actually flow into them. This fixes a variety of CPU leak issues with falling water in large water bodies such as oceans.
This also fixes the plus-shape effect that liquid is supposed to produce when a source is placed above ground.

* Removed a bad optimization making liquids flowing down slopes behave undesirably

* Optimize performance of slope searching by limiting recursion depth based on previous path lengths
If we already found a step down on a previous run after 2 blocks, it doesn't make sense to continue allowing checking 4 blocks because the results will just be ignored. This allows limiting the number of recursion steps, which significantly improves the performance when flowing down slopes.
However, this will still be just as bad for performance on flat terrain as it was to start with.

* Make some Liquid methods only accept Blocks as parameters
these are only ever passed blocks anyway, doesn't make sense to allow vectors.

* Moved some things to local variables
these are each only used in one function, so it doesn't make sense for them to be class members.

* Fixed water flow down slopes going everywhere, but degraded performance again

* Lava should only search 2 blocks for a slope

* Stop wasting CPU calculating optimal flow directions for liquids with too-high decay
It calculates the flow directions and THEN doesn't use them when it
realizes the flow decay is too high. This is completely pointless.

* Use a less hacky method to handle lava flowing into water

* Doubled flow performance on flat terrain
Since calculateFlowCost() usually ends up visiting the same blocks about 6 times when on flat terrain, it makes sense to cache some stuff for when blocks get revisited so expensive dumb checks don't need to keep on being done. On my machine this produces a 50-60% performance improvement when flowing on flat terrain.

* Fixed missing return values in Liquid->onUpdate()
these return values aren't used anywhere, but we should be consistent

* Don't allow flowing back in the same direction we just came from
This reduces the recursions by about 30%, providing about the same percentage performance improvement.

* Remove Liquid's temporalVector (it's not used anymore)
primitive types for the win!

* Move liquid collide to its own method

* add sound for lava/water mix
2017-12-04 10:09:35 +00:00
990a48d858 Better error message when a level is unloaded during its level tick
Plugins may cause this issue unexpectedly by unloading levels directly during events such as EntityDamageEvent. This adds a better error message to allow developers to understand what is going on and create appropriate workarounds.
2017-12-04 10:01:55 +00:00
af68125872 Make Level->getName() less volatile
this resolves problems with crashes when getName() is called on an unloaded level. This obviously doesn't solve the root cause of the issue (level being accessed after unload) but since many things use the level name without checking if it's unloaded first, it's a bad idea for it to be volatile.

This resolves the server crash issue noted in #1527, where an exception is raised due to level unload during a tick, which subsequently causes a crash when trying to log the exception.
2017-12-04 09:57:53 +00:00
5a0afa9f88 Fixed broken logic in EntityEffectEvents, close #1767 (#1768) 2017-12-03 16:14:20 +00:00
c301788864 API bump 2017-12-02 17:22:05 +00:00
472bf1a1ef Kill off the JSON garbage in commands
kill it with fire!
2017-12-02 16:33:19 +00:00
1a4b653d07 Color: Fixed a confusing inconsistency in documentation 2017-12-02 16:17:27 +00:00
d9f0546cb3 Added Color::mix() 2017-12-02 16:17:12 +00:00
92a1f45175 Make Living::addEffect() return bool (#1755) 2017-12-01 16:56:37 +00:00
0afe20c382 Remove redundant overridden meta property from Air 2017-11-30 11:10:07 +00:00
e94db980d7 Fixed not being able to wear armour 2017-11-29 19:51:38 +00:00
2cb81b5f8d NetworkInventoryAction: Allow returning null to ignore weird transactions
Revert "Return null on unmatched inventory action and log details"

This reverts commit fd7fb10223.
2017-11-29 12:44:41 +00:00
78cf875080 Quick-fix for crafting with big crafting grid after cancelling PlayerInteractEvent on a crafting table
this is not an ideal solution, but it works. Crafting is messy and is going to need more refactoring. Fixes #1480
2017-11-28 19:23:26 +00:00
878f1bffb9 CraftingTransaction: Don't hardcode crafting grid sizes 2017-11-28 17:29:53 +00:00
98ac6fc7be Check inventory slot is in range in SlotChangeAction 2017-11-28 16:56:02 +00:00
88318d740a Use standard subchunk iterator code in Explosion
this causes a slight performance loss (<10%), but in a sane language this would be inlined anyway
2017-11-28 11:20:22 +00:00
d3e5733ea0 Significantly improved light population performance using subchunk
direct accessing

These changes produce upwards of 2x better performance (YMMV, also
depends on the circumstances).
2017-11-28 11:20:22 +00:00
4703715063 Added a SubChunkIteratorManager class for faster subchunk handling 2017-11-28 11:20:14 +00:00
523a7f0999 Fix a very rare light propagation bug
This could occur when light sources were placed near each other and one of them is removed, the other's light would not be propagated far enough because the node wasn't queued for updating although it was marked as if it was.
2017-11-27 19:43:56 +00:00
256527c953 Chunk: Fixed possible bug with Chunk->setBlockData()
to be honest this would probably never affect anything, but let's be consistent.
2017-11-27 19:26:20 +00:00
b93691a177 Chunk: Remove redundant assignment 2017-11-27 18:58:08 +00:00
48c5db4296 Chunk: Add some PhpDoc 2017-11-27 17:51:42 +00:00
c564655f9b Chunk: Remove unnecessary default values
these are assigned in the constructor anyway.
2017-11-27 17:49:08 +00:00
49301b0d74 Chunk: Use an SplFixedArray for subchunks 2017-11-27 17:46:48 +00:00
8bc733514b LevelDB: Fixed nonsensical array access in iterator loop 2017-11-27 17:21:26 +00:00
c1a6711514 Fix for explosions modifying the wrong subchunks under some circumstances 2017-11-27 17:11:52 +00:00
f477cfa1bf Fixed a mistake in AvailableCommandsPacket 2017-11-25 11:15:20 +00:00
1f5f67e087 Liquid: Removed a bad hack-fix, fixed mobs not moving when water flows around them
this breaks more than it appears to fix, and I can't reproduce any CPU
leaks when block updates are enabled, so I'm going to assume this is OK.
2017-11-24 17:23:12 +00:00
74967eed87 Liquid: Stop abusing getLevel() in performance-sensitive situations
Most of these methods are called from onUpdate(). It's unreasonable to
assume that the level might be null during a tick (unless a plugin
messes with a block update event or something, but that's undefined
behaviour anyway). Using getLevel() simply wastes processing time by
constantly checking if the level is closed.
2017-11-24 16:58:03 +00:00
b88ffa3bdf Fixed a mistake in Block->getSide() documentation
side() -> getSide()
2017-11-24 15:09:55 +00:00
79fd9b1c96 added RottenFlesh item 2017-11-24 10:46:55 +00:00
ed195e1167 phpdoc 2017-11-23 17:27:41 +00:00
667a54fd00 Store world height in the Level for faster access
this might look like a micro optimization, but it shows up big-time on profiler snapshots.
2017-11-23 17:24:37 +00:00
b22b493abb Fixed Player->onDeathUpdate() not being called
I did not realize this was going to be a problem... argh! stupid messy player impl D:
2017-11-23 14:23:57 +00:00
0badaeb8f4 bump max dead ticks to 25 so death smoke cloud works properly
I wish this wasn't client sided... it's a pain to get it synced properly.
2017-11-22 19:55:25 +00:00
c5ac6a7606 Remove redundant count() for effects ticking 2017-11-22 19:44:22 +00:00
e9951b1b1f Remove redundant condition for setBreathing() 2017-11-22 19:43:09 +00:00
47f94eebd1 Use maxDeadTicks instead of hardcoded 20 2017-11-22 18:58:58 +00:00
e9e22db1e7 Cleaned up death animation handling, removed dead ticking from non-Living entities 2017-11-22 17:17:47 +00:00
75e469c380 Fixed bad parameter names due to old code additions in Block->place() 2017-11-22 14:26:55 +00:00
686e1c4470 Implement ender chest (#1462) 2017-11-22 14:25:21 +00:00
8d59843020 Order tile constants alphabetically 2017-11-22 14:00:41 +00:00
580b30b768 update versions 2017-11-22 13:51:40 +00:00
589ca45825 Updated RakLib dependency (again) 2017-11-22 09:43:33 +00:00
88ad43971a constant visibility 2017-11-21 16:50:27 +00:00
1fd9994056 Merge branch 'master' into mcpe-1.2.5 2017-11-21 16:48:18 +00:00
808227d9a9 Hack for player spawning issue (ref. #1539) 2017-11-21 15:20:56 +00:00
74b074753f Bulk addition of constant visibilities
thanks PhpStorm inspections plugin for annoying the shit out of me until
I did this.
2017-11-21 14:44:10 +00:00
3f854127ca Updated RakLib depdendency 2017-11-21 14:36:23 +00:00
9da19b5f15 Added API methods for getting & setting armour dye colours 2017-11-21 14:10:33 +00:00
78d24b9183 Take 2: Fixed resource pack matching for uppercased UUIDs
fixed the wrong damned bug...
2017-11-21 11:29:12 +00:00
46afb7caf1 Fixed resource pack matching for uppercased UUIDs 2017-11-21 11:25:21 +00:00
0ee452773d Fixed missing getValue() implementation on CompoundTag 2017-11-21 10:52:00 +00:00
a39c9e8c8e add ResourcePack->getPath(), close #1559 2017-11-20 13:24:30 +00:00
32714d4564 Don't write server.properties to disk unless it's been modified at runtime 2017-11-20 10:04:39 +00:00
feade9d982 Added a flag to Config to allow detecting if it has been modified since it was last saved 2017-11-20 10:04:11 +00:00
373f085436 Fixed a usage of get(true) 2017-11-20 09:50:52 +00:00
d2416d335e Use keepMovement in spectator and when movement anti-cheat is disabled
this makes it much less expensive for players to move around when anti-cheat is disabled. And let's be honest... who uses this shit anyway
2017-11-19 19:31:03 +00:00
a8ad956b29 Fixed keepMovement logic 2017-11-19 19:28:04 +00:00
00a9ae6c95 make use of getSavableEntities() in Level->unloadChunk()
why couldn't I have thought of this before I changed this the first time >.>
2017-11-19 18:08:42 +00:00
a9df383346 generalized conditions for saving entities with chunks 2017-11-19 18:06:38 +00:00
19dc22d6b3 Chunk save: skip entities which won't be saved anyway
don't just hardcode this to players
2017-11-19 17:57:54 +00:00
2fd61163bf cleanup some chunks leftovers from 1.0 2017-11-19 17:52:36 +00:00
5640bcb0b8 add some new leveldb keys 2017-11-19 17:43:54 +00:00
ea3c7383fb Added support for handling MCPE 1.2 leveldb worlds
requires php-leveldb version >=0.2.1 and the latest version of
pmmp/leveldb-mcpe
2017-11-19 17:31:09 +00:00
7e496afdd1 Fixed issues with LevelDB worlds silently getting overwritten with the default format when LevelDB extension is not loaded
Always register the level provider (to allow detecting the world format) but throw exceptions if anything tries to use it without the extension being loaded.
2017-11-19 17:28:16 +00:00
3bc3a0bb49 Remove redundant inventory resend on gamemode change
inventory isn't modified, so there is no need to resend it
2017-11-19 15:34:29 +00:00
c75e62b38c Fix /gamemode output again 2017-11-19 15:28:34 +00:00
3a80ec4db8 Add bed too far message 2017-11-19 10:22:04 +00:00
8abad33048 Change TextFormat::WHITE to RESET in Server.php 2017-11-19 10:22:04 +00:00
a91a4489d4 Updated PocketMine-Language submodule 2017-11-19 10:21:06 +00:00
96348e0e44 Fix setMaxAirSupplyTicks() (#1555) 2017-11-19 01:40:46 +00:00
dd8a772d43 Removed handler for PlayerHotbarPacket
this thing is useless now, and the equipment stuff can be done with MobEquipmentPacket anyway.
2017-11-18 16:03:18 +00:00
dc553142c9 Remove redundant if/else in Player->checkGroundState() 2017-11-18 15:59:51 +00:00
81fe00a0a5 Slightly simplify Player->kick() 2017-11-18 15:56:58 +00:00
6facd8b50f Provide a way for plugins such as Specter to bypass chain verification 2017-11-18 12:44:18 +00:00
e709e3c653 Allow skin geometry name field to be missing
it's not needed, and plugins doing this might want to skip it
2017-11-18 12:32:31 +00:00
eaba105614 Durable: use new CompoundTag API 2017-11-18 11:13:35 +00:00
12bbc764ec Fixed Level->getSafeSpawn() looking for blocks in chunk 0,0 2017-11-17 20:45:29 +00:00
bee3c4f5cd Cleaned up error messages for submodules (they are Composer dependencies now) 2017-11-17 19:56:05 +00:00
bda40edebe Fixed default level spawning bug reported on forums
https://forums.pmmp.io/threads/pocketmine-mp-version-1-7dev-399-error-listtag-members-must-be-namedtags-got-integer-in-given.4561
2017-11-17 16:59:57 +00:00
5178373d8a fixed overoptimized code in getSafeSpawn(), close #1248 2017-11-17 13:58:03 +00:00
28188e5ef4 remove redundant count() for updateTiles 2017-11-17 13:47:54 +00:00
7c2dccd2a6 Replace Player->joined with Player->spawned, remove redundant field
spawned serves basically the same purpose as joined does.
2017-11-17 13:44:37 +00:00
adabfe78df no-op for PlayerAction START_SLEEPING
this is pretty pointless tbh
2017-11-17 13:30:25 +00:00
0fdceb6736 Remove useless sendNextChunk() condition
if the load queue is empty, it makes no difference whether we're spawned or not.
2017-11-17 13:24:31 +00:00
ffa9a91a95 Remove dead craftingType field from Player 2017-11-17 12:57:49 +00:00
78bb951942 Remove redundant survival check for exhaustion 2017-11-17 12:55:48 +00:00
7508524b7b Arrange login sequence code in a bit more chronological order 2017-11-17 12:47:57 +00:00
db4a8be240 Remove duplicated duplicated player code in Player 2017-11-17 12:39:12 +00:00
3fe9963c84 remove redundant arguments for Entity methods 2017-11-17 12:19:36 +00:00
db8a835a64 add a default value for Entity->setCanClimb() 2017-11-17 12:19:04 +00:00
460d540dbc Further cleanup on ListTag and CompoundTag usage 2017-11-17 11:43:32 +00:00
665130561e Further cleanup on NBT dynamic field access
not sure how I missed so many of these... there are probably lots more besides :(
2017-11-17 11:19:36 +00:00
48a7627b96 add constants for NBT tag names in WritableBook 2017-11-17 10:48:48 +00:00
235fc4cd2f remove redundant null coalesce 2017-11-17 10:45:14 +00:00
e0654b85ba get rid of dynamic field assignments
nearly there now... eventually
2017-11-17 10:43:51 +00:00
19315dfd06 Some cleanup on WritableBook code, get rid of some CompoundTag magic 2017-11-17 10:43:51 +00:00
f3ee605cd3 ignore doxygen files 2017-11-16 16:37:30 +00:00
976d5583cc Remove ItemFrame drops hack 2017-11-16 15:13:22 +00:00
6adc813a7f Fixed disable-block-ticking pocketmine.yml config not working 2017-11-16 14:45:00 +00:00
769f3f75cd added public doxygen configuration 2017-11-16 10:38:39 +00:00
432d90bddd quickfixes for command messages
these will have to be fixed properly at a later date
2017-11-16 08:56:01 +00:00
3a16985d45 Cleaned up item & arrow pickup code 2017-11-15 12:14:42 +00:00
bbbed22467 Save player data after PlayerQuitEvent (#1544), close #1543, close #1482
This reverses a bad solution for #1482 for level unloading on PlayerQuitEvent which caused more widespread issues with plugins doing other, more common things on player quit which directly affected the save data.
2017-11-15 11:16:02 +00:00
2794df34ab Basic implementation of banners, including API to modify them with ease. (#1331)
Banner crafting is NOT implemented yet.
2017-11-15 11:10:46 +00:00
73cd195e76 Merge branch 'master' into mcpe-1.2.5 2017-11-14 20:06:00 +00:00
0d2b171c2c Remove RakLib and SPL submodules, start using Composer 2017-11-14 19:37:58 +00:00
aa399a1109 migrate to new CompoundTag API (#1515) 2017-11-10 15:38:21 +00:00
d4494687d1 Fixed collision blocks not being recalculated after teleporting, close #1531 2017-11-09 15:11:42 +00:00
6fe45a69c8 Updated RakLib submodule 2017-11-09 14:44:38 +00:00
784ecef805 Remove unnecessary count() 2017-11-08 19:44:10 +00:00
41f363d0c1 Added encode for AvailableCommandsPacket, bring back command lists (no arguments yet) 2017-11-08 11:52:06 +00:00
827ee5ff33 more constants in Tile 2017-11-08 10:49:15 +00:00
a4e955c0a4 Merge branch 'master' into mcpe-1.2.5 2017-11-07 15:27:14 +00:00
733e61f815 add return typehints for Item fluent methods
to prevent issues like a2d4baf8b9 happening again >.>
2017-11-07 09:54:08 +00:00
0621d5c8ea Fixed JSON NBT parsing lists in /give 2017-11-07 09:50:59 +00:00
a2d4baf8b9 Fixed ItemBlock->setDamage() not returning a value 2017-11-07 09:44:34 +00:00
23bc97e098 Updated PocketMine-DevTools submodule 2017-11-07 09:36:58 +00:00
14e6e3694d Updated RakLib submodule 2017-11-07 09:35:00 +00:00
0e64c3dad8 fixed misusing isAlive(), close #1523 2017-11-07 09:32:38 +00:00
99f06c6c18 Fixed player hit animations 2017-11-06 14:41:48 +00:00
3ca9e6ae98 Merge branch 'master' into mcpe-1.2.5 2017-11-06 14:35:10 +00:00
fd0b07a0aa Added API to allow getting player latency 2017-11-06 14:33:27 +00:00
6ece799998 Updated RakLib submodule 2017-11-06 09:09:20 +00:00
a9c75a882a Updated PocketMine-SPL submodule 2017-11-05 20:51:26 +00:00
4437b67178 added some EntityEventPacket constants 2017-11-05 12:41:39 +00:00
34d2047ac3 A better error message for Server::getInstance() access on other threads 2017-11-05 18:40:47 +08:00
20d2ef9d38 Fixed players respawning in the wrong world
add() returns a Vector3 instance, not a Position instance... argh
2017-11-04 22:04:33 +00:00
eab7b93483 Fixed misuse of kill() and close() when deleting entities (#1490) 2017-11-04 19:30:48 +00:00
e84ab8fec2 Disable stats reporting by default on new installs
since we don't have a stats server at the moment, this simply causes long delays on server stop while the server instance attempts to communicate with stats.pocketmine.net.
2017-11-04 18:41:18 +00:00
a66a757f56 Cleaned up EntityEventPacket handling 2017-11-04 18:31:35 +00:00
ddb7fd12f2 removed obsolete EntityEvent broadcast 2017-11-04 18:28:29 +00:00
6ccb494f8d added API to get player language code
sadly this isn't particularly useful without something like the intl
extension to translate the language codes to ISO-632-1 codes like the
ones PocketMine-MP uses. However, this will do for now.
2017-11-04 15:50:00 +00:00
2ec7763bd6 Cosmetically improve UUID::equals() (#1517) 2017-11-04 10:45:05 +00:00
d663887f9c Merge branch 'master' into mcpe-1.2.5 2017-11-03 16:43:34 -04:00
6ebe3bfbea use Player->sendDataPacket() with immediate parameter 2017-11-03 19:00:08 +00:00
4533df17cf make username validation on login less stupid
why are we checking if the username is valid AFTER we already tried to set it? it might not even be a string
2017-11-03 18:49:28 +00:00
8ae663425f try...catch attempt to decode connection request in incompatible logins
to allow protocol version hacking without it being so damn inconvenient
2017-11-03 18:46:40 +00:00
e95b1d4b00 look for item IDs in ItemIds instead of Item
Item is likely to be more polluted by other constants which aren't item IDs.
2017-11-03 12:42:51 +00:00
8ad02c9a4e Remove redundant condition from ItemFactory
it's unrealistic to have a numeric constant name, so this condition is pointless.
2017-11-03 12:41:24 +00:00
754e088ee8 Change visibility of Block->boundingBox 2017-11-03 12:19:51 +00:00
451f5d0cd7 Fixed block-pick on crops giving the crop block itself 2017-11-03 12:17:38 +00:00
42ed03fd02 Merge branch 'left-click-spawn-prot' 2017-11-03 11:59:26 +00:00
b51ec9e606 rough work for CommandOutputPacket, no idea if it works 2017-11-01 20:12:13 +00:00
8d07f833fc updated CommandRequestPacket 2017-11-01 20:11:31 +00:00
372b97ba8f Revert "Patch %0 client translation exploit"
this bug was (FINALLY) fixed in 1.2.5.15

This reverts commit 378c3d7994.
2017-11-01 16:17:17 +00:00
dea2942062 bump to 141 2017-11-01 16:14:12 +00:00
3614711a02 fixed negative effect durations when level tick rate is > 1
thank you @Sandertv
2017-11-01 09:09:17 +00:00
dcdea6a1f4 Merge branch 'master' into mcpe-1.2.5 2017-10-31 21:52:16 +00:00
b7cd8dbfa9 Fixed CraftingManager->cloneItemMap() being utterly useless 2017-10-31 19:01:03 +00:00
1486b5aa71 make more properties in CraftingManager protected 2017-10-31 18:49:49 +00:00
f8e6438efe updated some NBT for tiles 2017-10-31 18:22:06 +00:00
caf9eaa2da rename field in EntityPickRequestPacket 2017-10-31 12:25:20 +00:00
6db5596b00 Added Jukebox window type ID 2017-10-30 18:37:42 +00:00
4ed1a39638 Updated DevTools submodule 2017-10-30 17:06:33 +00:00
a770e681dc Implemented Config->removeNested() (#1499) 2017-10-30 16:32:48 +00:00
a342a61037 nuke nestedCache when config is modified 2017-10-30 16:27:47 +00:00
91c256f1a9 Added Level->getTileAt() 2017-10-30 13:36:42 +00:00
93443992be Fixed chests not getting updated properly on pair/unpair, close #1514
it wasn't clearing spawn compound caches or chunk caches
2017-10-30 11:50:02 +00:00
ea09cc06c7 added UUID constants for MultiRecipe 2017-10-30 11:18:56 +00:00
67af4d3b65 Cleaned up PMAnvil implementation 2017-10-29 19:13:58 +00:00
4a78bfaa18 stop messing with my doc comments PhpStorm 2017-10-29 18:02:33 +00:00
bb6b100443 extended CompoundTag API to allow force-writes and returning defaults on bad tag types 2017-10-29 18:01:33 +00:00
8aca373194 added some docs to shut PhpStorm up 2017-10-29 13:02:19 +00:00
7e490ccdf2 broadcast player skin to all online players by default
otherwise we could end up with undesirable bugs like players having the wrong skin when travelling from another part of the world... the skin has to be sent to everyone to update the player list
2017-10-29 12:19:47 +00:00
991d321928 improved geometry debloating, also apply on skin changes 2017-10-29 12:14:16 +00:00
600d80331a Accept null for targets in Human->sendSkin()
For humans, it'll send to all viewers. For players, it'll send to all viewers, and the player itself.
2017-10-29 11:18:34 +00:00
f79e4237df Cache a compressed CraftingDataPacket to reduce workload on player join
this saves only a couple of ms per player join, but still worth it.
2017-10-29 09:57:55 +00:00
6ce9e79cd5 fix some minor documentation issues in Binary 2017-10-28 18:40:05 +01:00
e88aa385a3 make use of new pack() codes for longs 2017-10-28 14:04:41 +01:00
5303a710ac Updated RakLib submodule 2017-10-28 10:26:34 +01:00
dd085b35cc Merge branch 'master' into mcpe-1.2.5 2017-10-27 21:24:30 +01:00
6ff1088a57 fix chest AABB 2017-10-27 19:16:06 +01:00
d1db27016e s/facePos/clickVector/
clickVector better describes this
2017-10-27 19:05:26 +01:00
c55bc2d7e9 added use-item click vector to PlayerInteractEvent
now go and make some touchscreens with maps!
2017-10-27 19:00:17 +01:00
747477dfcf Changed potentially misleading parameter name in CompoundTag->getTagValue() 2017-10-27 11:04:03 +01:00
48fefae920 Added cache for tile spawn compounds
avoids expensive repetetive NBT writes on chunk sends when the tile hasn't been changed
2017-10-27 10:23:48 +01:00
52d0ad8a61 be yet more tolerant for on-ground checks on players 2017-10-26 23:23:11 +01:00
bddd7e0eee Fixed no fall damage when falling 3-4 blocks, close #891 2017-10-26 23:23:08 +01:00
883898682f Merge remote-tracking branch 'origin/master' into mcpe-1.2.5 2017-10-26 15:34:56 -04:00
daf457213d Updated RakLib submodule 2017-10-26 16:35:33 +01:00
bd2cb85861 changed type of EntityLink unknown field and added a constructor 2017-10-25 18:50:07 +01:00
1d651046c9 Compute time in milliseconds once and use it for both firstPlayed and lastPlayed
fixes issues where lastPlayed can be a tiny fraction of time into the future of firstPlayed when players join for the first time
2017-10-25 17:12:17 +01:00
1dea25d123 Fixed wrong translation key used for level generation errors 2017-10-25 16:42:49 +01:00
b6264d188e Change Server->getConfigBoolean() to getConfigBool()
to be consistent, deprecated the original
2017-10-25 16:30:39 +01:00
2635c85873 beware users putting garbage in pocketmine.yml 2017-10-25 12:54:53 +01:00
3b85e558ce Fixed bad documentation on Level->checkSpawnProtection() 2017-10-24 18:56:38 +01:00
d48880e31b Remove redundant assert 2017-10-24 17:40:22 +01:00
93d60a9beb Updated DevTools submodule 2017-10-24 16:23:04 +01:00
a82efc44aa wtf 2017-10-24 13:29:28 +01:00
6daa0135d5 Cancel PlayerInteractEvent automatically on left-click block when spawn protection is triggered 2017-10-24 13:11:19 +01:00
08092f17e0 Merge branch 'master' into mcpe-1.2.5 2017-10-24 10:24:37 +01:00
716c1f29b4 Fixed slabs again 2017-10-24 10:23:07 +01:00
0072af95cb Bump version to 1.2.5.12 and protocol changes 2017-10-23 20:04:47 +01:00
0df3b00de4 Fixed incompatible protocol message showing an empty pair of brackets when protocol is null
this happens if an exception occurs while or before trying to read the protocol version
2017-10-23 19:44:19 +01:00
13e5718463 Using BlockFactory instead of Block 2017-10-23 18:50:37 +01:00
270e0c076c Fixed items not removed when put in the lava 2017-10-23 18:50:37 +01:00
3765511317 rename WritableBook->swapPage() to swapPages() 2017-10-23 17:55:01 +01:00
8daa8deae9 Added Living->lookAt() 2017-10-23 17:29:20 +01:00
e055ce9526 Use translation for flight kick message (#1489) 2017-10-23 13:18:57 +01:00
3ed8855894 fix drop chance of rotten flesh 2017-10-23 12:35:57 +01:00
f25255e46c fix zombie drops 2017-10-23 12:24:34 +01:00
7db8345424 Added rough support for reading entity saves with multiple save IDs (for PC 1.11 compatibility)
this will still always save using the legacy format to remain compatible with PC < 1.11.

TODO: entirely separate entity NBT format from entity implementation for proper multi-format compatibility
2017-10-22 10:16:24 +01:00
bc7ba3b3c1 Found field of ShowProfilePacket 2017-10-21 14:53:49 +01:00
1dd2203ee5 Fixed burning mobs not getting onfire data flag set when read from disk
they'd just flash red and take damage for no apparent reason
2017-10-21 12:36:30 +01:00
554096953b Abuse property visibility to micro optimize CompoundTags
this produced a little less than 10% performance improvement under xdebug, and while the real-time benefit is negligible, it's harmless to have.
2017-10-20 20:07:54 +01:00
55a1731da3 Remove redundant asserting function in Binary
If this was an inline assert, it would be harmless. Since it's in a function, it contributes to a 20% performance loss when using these functions on a large scale regardless of whether assertions are enabled or not.
Additionally, there's no need to assert that we have enough bytes since unpack() will raise warnings if there isn't, which will trigger exceptions, and for readByte(), an undefined offset notice will be raised, which will also trigger an exception.

TL;DR: This is simply wasting CPU time for no good reason.
2017-10-20 19:23:04 +01:00
ba3fe20227 Fixed missing variant bitmask for Leaves, close #1478 2017-10-20 18:37:46 +01:00
7b04049bb7 Throw exceptions when trying to add closed entities or tiles to levels 2017-10-20 18:22:28 +01:00
30211bee82 Fixed excessive idle CPU usage for chunk ticking
"excessive" = 5%, after changes = 1.6% - YMMV, but that's my machine.
2017-10-20 15:54:22 +01:00
e318dc12a5 missed target 2017-10-20 15:36:59 +01:00
967ce99b03 Made incompatible PHP version messages more useful 2017-10-20 15:35:43 +01:00
9bdda54aec Fixed PocketMine.php compatibility with < PHP7 2017-10-20 15:34:03 +01:00
18e4e5364f Fixed getBlock() performance degradation caused by 781de3efab, added Level->getBlockAt() to avoid creating vectors everywhere 2017-10-20 13:22:49 +01:00
98cfd0b398 fix entity rotation changes not getting broadcast until the entity moves 2017-10-20 10:13:19 +01:00
a245615531 fixed non-living entities lingering for a second after being kill()ed
only living entities should have death animation time
2017-10-19 20:51:50 +01:00
0a19a2611a Re-organise some Entity methods 2017-10-19 19:03:11 +01:00
50be26958a Added a helper function Entity->createBaseNBT() to cut down on boilerplate code 2017-10-19 17:36:51 +01:00
67c6fca0ed Relocate a couple of Entity API methods and add some documentation 2017-10-19 17:05:27 +01:00
d99e9513b0 Remove some redundant constructor overrides 2017-10-19 16:42:14 +01:00
5a353012de Clean up some unused imports 2017-10-19 16:39:34 +01:00
087badcb48 Remove deprecated effects methods from Entity 2017-10-19 16:35:44 +01:00
d9769360fe Remove redundant code from Entity->entityBaseTick()
this will never be called because onUpdate() checks this and returns.
2017-10-19 16:32:45 +01:00
9fb93985d6 Cleaned up Entity->spawnTo() 2017-10-19 16:13:09 +01:00
2b22d5d8cc Added EntityIds interface with constants 2017-10-19 15:43:55 +01:00
2db13bd114 added throwable eggs and refactor some projectile logic
close #1473
2017-10-19 14:12:50 +01:00
11cc20972f extended death animation time 2017-10-19 13:39:51 +01:00
4821e7386d fixed entities despawning too soon when killed 2017-10-19 13:39:10 +01:00
584810780a Moved projectile-related classes to their own namespace 2017-10-19 12:27:44 +01:00
55de75b914 Let blast resistance be computed from hardness for flowable blocks
fixes several flowable blocks apparently not having any resistance to explosions
2017-10-19 11:50:21 +01:00
2a1a17aa7a Refactored button code, fix placement rotation 2017-10-19 11:36:30 +01:00
90165cf99d Implemented farmland hydration
TODO: make crops take notice of this
2017-10-19 11:23:54 +01:00
a4ca3f1d1c Updated PocketMine-Language submodule 2017-10-18 21:08:39 +01:00
f783789e5a fixed escape code unescaping in language files, close #1474 2017-10-18 20:43:35 +01:00
43be64baed Register some more items
the item-blocks will allow their blocks to be placed, but they still won't work until the blocks themselves are added.
2017-10-18 19:52:19 +01:00
5c92c8a9d3 added red sandstone and red sandstone stairs 2017-10-18 19:42:12 +01:00
d2dc49cd9c Refactor Slab logic away from WoodenSlab, added StoneSlab2 and its double 2017-10-18 19:27:54 +01:00
f148c366f9 Use Block->getVariant() more, get rid of hardcoded bitmasks 2017-10-18 17:46:24 +01:00
91d84aaff4 Fixed a direct Block construction that PhpStorm somehow couldn't see 2017-10-18 17:03:55 +01:00
6b78ba8c25 replace some hardcoded values with Vec3 constants 2017-10-18 17:03:18 +01:00
b9de2e8b4b Use bit operations for rotations instead of hardcoded values 2017-10-18 16:47:37 +01:00
15764543b4 Use PillarRotationHelper for hay bales 2017-10-18 16:41:43 +01:00
2c34648c3d fixed second half of double chest items getting deleted, close #1477 2017-10-18 12:29:57 +01:00
3e3157cbe1 fix tick diff debug spam when entities are spawned 2017-10-17 17:38:43 +01:00
07abd61f73 Added a FIXME for Entity->move() 2017-10-17 17:14:45 +01:00
a456b7cfca Disable movement anti-cheat by default
shit's useless and an annoyance.
2017-10-17 16:45:18 +01:00
ece37d1e19 Added more methods to PlayerIllegalMoveEvent 2017-10-17 16:14:41 +01:00
cccaade00c make Player#unloadChunk() method protected 2017-10-17 14:22:57 +01:00
7f0a961526 "Creator" tag on signs may not exist 2017-10-17 13:35:31 +01:00
68ac4f538f Added ContainerTrait, reduce copy-pasted code in Tile 2017-10-16 20:01:17 +01:00
f14b7cbf78 Renamed BlockEventPacket fields 2017-10-16 19:55:42 +01:00
f4ff5d81ea Added missing parent calls for saveNBT() in Chest and Furnace 2017-10-16 18:56:48 +01:00
28a840d161 Make use of CompoundTag->hasTag() 2017-10-16 18:32:08 +01:00
292e462ea0 Remove nullable return types on CompoundTag getters
this doesn't make sense because there are default value parameters for this
2017-10-16 18:22:45 +01:00
c8379efbce Added expectedClass parameter to hasTag() to allow type-checking 2017-10-16 17:26:12 +01:00
1b5746fd97 Use NamedTag::class for default expectedClass in CompoundTag->getTag() 2017-10-16 17:22:38 +01:00
4a0ac01697 Fix PhpStorm derp
wtf?
2017-10-16 17:02:00 +01:00
9bcb41fb21 Refactor misleading parameter names in CompoundTag
these are NBT tag classes, not the NBT tag type. The tag type is an integer which describes the tag on disk.
2017-10-16 17:00:57 +01:00
20b86bdea8 Cleaned up tile NBT handling, use new CompoundTag API methods 2017-10-16 16:48:24 +01:00
0b1a9ba062 Added more typehints to Tile namespace 2017-10-16 16:14:44 +01:00
45b003ac2e Removed unnecessary return from Sign 2017-10-16 16:10:33 +01:00
769a50faa5 Refactor confusing parameter names for Item->onActivate()
next: refactor the function itself
2017-10-16 13:30:36 +01:00
af85659c63 Remove redundant property from Tile 2017-10-16 12:35:32 +01:00
95fa1824c8 Use a trait for nameable tiles instead of repeating code 2017-10-16 12:32:10 +01:00
251d5d7946 Fixed some hardcoded values in Tree 2017-10-16 12:30:46 +01:00
3b5eb45ff5 More usages of Item->isNull() 2017-10-16 12:29:39 +01:00
fd847f02ad Added BaseInventory->dropContents() 2017-10-16 12:18:06 +01:00
18d3a97466 Anvil result slot is not a real inventory slot
like the crafting grid result slot, this doesn't actually exist, it's
just somewhere you get the result item from.
2017-10-16 12:00:43 +01:00
04668d534d Oops, these fields need to be filled 2017-10-16 11:50:34 +01:00
092cc2750f Added entity unique ID for Entity containers
minecart with chest for example
2017-10-16 11:49:34 +01:00
68809d992b Added BaseInventory->removeAllViewers() 2017-10-16 11:15:03 +01:00
1641183674 added some typehints to Item 2017-10-16 10:29:44 +01:00
72531209bf Added some constants for frequently-accessed item NBT tags 2017-10-16 10:24:32 +01:00
8c6ab3e634 Some cleanup to item NBT handling 2017-10-16 10:15:41 +01:00
97e2d64592 "Fixed" shift-clicking recipe book, close #1401
this is not an optimal solution because you'll still only get 1 crafting
event when the user actually crafted a lot of items, so this isn't very
nice for plugins to work with. However, for gameplay purposes it works,
so it'll do for now.
2017-10-15 18:08:32 +01:00
a547e2cca8 Fixed sub-optimal code in WritableBook 2017-10-15 10:14:02 +01:00
cdebb62c35 added typecast for forceLanguage property read 2017-10-14 23:26:00 +01:00
2e73fd7f8c Add missing setValue() override to LongTag
why did this take two commits ;-;
2017-10-14 22:24:17 +01:00
51906daad0 Add typehints and PhpDoc to NBT API 2017-10-14 22:07:25 +01:00
ce67bc620a add Travis Test data directory to gitignore 2017-10-14 22:06:07 +01:00
bcefc3a54b Flag expectedType as nullable 2017-10-14 20:45:37 +01:00
f5378ab604 Fixed assertion failure when using getTag() without specifying an expected type 2017-10-14 20:45:32 +01:00
dab7cfde1c Added new API methods in CompoundTag to allow developers to stay sane (#1469)
Added getters and setters to CompoundTag with type safety
we need generics so badly here it hurts

This is fully backwards compatible, however the following API methods have been added to the `CompoundTag` class:

- getTag(string $name, string $expectedType = null) : ?NamedTag
- getListTag(string $name) : ?ListTag
- getCompoundTag(string $name) : ?CompoundTag
- setTag(NamedTag $tag) : void
- removeTag(string ...$names) : void
- hasTag(string $name) : bool

- getTagValue(string $name, string $expectedType, $default = null)
- getByte(string $name, ?int $default = null) : ?int
- getShort(string $name, ?int $default = null) : ?int
- getInt(string $name, ?int $default = null) : ?int
- getLong(string $name, ?int $default = null) : ?int
- getFloat(string $name, ?float $default = null) : ?float
- getDouble(string $name, ?float $default = null) : ?float
- getByteArray(string $name, ?string $default = null) : ?string
- getString(string $name, ?string $default = null) : ?string
- getIntArray(string $name, ?array $default = null) : ?array

- setTagValue(string $name, string $tagType, $value) : void
- setByte(string $name, int $value) : void
- setShort(string $name, int $value) : void
- setInt(string $name, int $value) : void
- setLong(string $name, int $value) : void
- setFloat(string $name, float $value) : void
- setDouble(string $name, float $value) : void
- setByteArray(string $name, string $value) : void
- setString(string $name, string $value) : void
- setIntArray(string $name, array $value) : void
2017-10-14 18:36:02 +01:00
6e1318b522 Push minimum requirement to PHP 7.2.0RC3
there are needed ZTS bugfixes included in RC3. I didn't move this earlier because Travis didn't have an RC3 build.
2017-10-14 14:26:21 +01:00
cd8006e242 Use constructor parameter for ListTags instead of setTagType() and removed some unnecessary type setting 2017-10-14 13:49:24 +01:00
f5abed95ec added missing type doc to ListTag 2017-10-14 12:48:38 +01:00
489b9fc29b Added missing getter override for LongTag
adds a return typehint
2017-10-14 11:34:41 +01:00
b524b841c5 Reduced duplicated code in AxisAlignedBB->calculateIntercept() 2017-10-14 11:01:00 +01:00
41f292d995 BlockUpdateEvent doesn't allow changing the target block anyway 2017-10-14 10:10:19 +01:00
fd8a562e02 Fixed collision bugs caused by not clearing pre-computed outdated AABBs for blocks
take fences as an example: say you have fence1 and fence2 next to each other, like this:
|==|
and they are joined together
then delete the fence on the right
the left fence will then look like this
|
but the server would still think its collision boxes were like this:
|=
so you wouldn't be able to shoot arrows through that space.

This commit clears pre-computed bounding boxes when a block is set using Level->setBlock() (in case the block was previously already set and has pre-calculated outdated AABB). However, because of weird blocks like fences, glass and walls, they must also be cleared on neighbour block update (since connection state isn't shown in the block data).
2017-10-14 10:07:17 +01:00
cc553a157d Clean up BlockEventPacket handling for Chests and fix wrong data for chest open 2017-10-13 20:07:33 +01:00
a6d1cc27ec Fix for explosions not removing tiles, close #1450 (#1463) 2017-10-13 13:57:50 +01:00
d8c90be5b8 Make on-ground checking less fussy 2017-10-13 13:19:20 +01:00
060426ff12 Add ability to unregister a command completely, close #1229 (#1464) 2017-10-13 11:55:36 +01:00
eeea4fa06a Added some new blocks 2017-10-13 11:51:38 +01:00
401e33dd85 fix anvil bounding box 2017-10-13 11:18:19 +01:00
2893aac3ac ... 2017-10-13 11:06:10 +01:00
c5c74c1898 fixing glass & bars collision detection
so much duplicated code, it would be nice if Fence could inherit from Thin, but that causes too many issues with block connections.
2017-10-13 11:04:51 +01:00
423bea4b57 Fixed a couple of blocks incorrectly descending from Solid 2017-10-13 10:37:48 +01:00
e3567faa94 Anvils aren't non-solid, they are transparent
solid and transparent are not mutually exclusive!
2017-10-13 10:22:22 +01:00
4b5040dcc7 Blocks extending Thin ARE solid 2017-10-13 09:52:08 +01:00
21c79b0645 Use up to 2 AABBs for fence collision checks instead of 5
overlapping cuboids do fine
2017-10-13 09:40:29 +01:00
7b5df10b6a Reset position properly when reverting movement 2017-10-12 20:33:26 +01:00
c4fe9ad32d Remove pointless API method from PlayerMoveEvent 2017-10-12 19:59:32 +01:00
60b62a4890 fixed wall collision detection
walls have to be weird...
2017-10-12 19:36:06 +01:00
061a9444cc implemented multi AABB collision checks for fences and walls
fixes anti-cheat getting triggered when falling down between a square of fences
fixes not being able to shoot arrows between a square of fences
2017-10-12 18:33:26 +01:00
3eb73ab468 Abstracted Fence code away from wooden fences 2017-10-12 17:04:49 +01:00
15d6fd86e2 Added basic support for blocks with multiple AABBs, fixed stairs (#1303) 2017-10-12 16:29:24 +01:00
0c092a7ceb reduced size of arrow bounding box
as per MCPE addon data
2017-10-12 16:21:23 +01:00
b9501ef415 Remove unnecessary duplicated ray-trace code from Block
this isn't actually used anywhere, but "backwards compatibility"
2017-10-12 13:40:12 +01:00
5afe4fdb5b Use Vector3 constants instead of hardcoded integers 2017-10-12 13:32:17 +01:00
cc7ed7a28f Added some documentation to AxisAlignedBB 2017-10-12 12:22:13 +01:00
7e9b89e48a Make Entity->checkObstruction() less confusing 2017-10-12 11:59:02 +01:00
63fccd4682 farmland and grass path should die when a solid block is above them 2017-10-12 11:11:33 +01:00
35e7aca88f refactor some more stupid variable names 2017-10-12 10:45:22 +01:00
9413f155ce implement updating properly for multi-face vines 2017-10-12 10:21:08 +01:00
6569fdbe04 Refactor some variable names in Vine 2017-10-11 20:12:12 +01:00
d8b1757ebc added some nullable and void typehints to Block API 2017-10-11 18:45:40 +01:00
8f0ee84277 Cleaned up Ladder AABB calculation code 2017-10-11 18:25:16 +01:00
b7a9e10d49 Some cleanup to how tiles are created 2017-10-11 18:08:08 +01:00
be2d134994 Added API to allow flagging an entity not to be saved to disk when its chunk is saved (#1452) 2017-10-11 16:09:08 +01:00
7b1bfc0520 fix some typos in pocketmine.yml 2017-10-11 13:42:32 +01:00
59d9d6a7df Fixed logic for low memory chunk radius override 2017-10-11 13:40:13 +01:00
8d095dff6c Given some MemoryManager fields less confusing names 2017-10-11 13:27:33 +01:00
4981931c4a Remove reliability hacks for RakLib
bug was fixed in 691a7be66b
2017-10-11 10:59:27 +01:00
5dafabbec2 Updated RakLib submodule 2017-10-11 10:59:27 +01:00
2a5d954c67 fixed yaw/headyaw field order
I wish they'd stop changing this shit... this is the third or fourth time now?
2017-10-10 22:45:30 +01:00
287f08cbd1 Changed confusing MovePlayerPacket field name to be consistent with other packets 2017-10-10 21:56:17 +01:00
76469e1d5f Remove useless properties from pocketmine.yml
these have been here for years but have never been of any use, they just confuse new users.
2017-10-10 00:01:05 +01:00
c4c83e23ca Revert RakLib to 1830bb7
disconnect & transfer issues... no idea why
2017-10-09 20:30:44 +01:00
eccc7bf7b3 Moved EntityLink to its own type 2017-10-09 19:15:53 +01:00
78ca2f2e58 fix heads rotating 45 degrees when placed facing north 2017-10-09 18:12:56 +01:00
cef9c4621c added som PhpDoc to Tile 2017-10-09 17:27:34 +01:00
151681bd80 Remove some dead properties from Tile 2017-10-09 17:25:10 +01:00
327907988b Fixed a typo in Sign->setText() docs 2017-10-09 16:56:25 +01:00
97dbf61236 Remove some no-longer-needed item classes 2017-10-09 12:31:57 +01:00
2be8b576ef Changed constructor of ItemBlock to allow handling blocks with different item IDs, added more doors 2017-10-09 11:58:58 +01:00
6dbdefafdd Add the long-awaited Enchantment::registerEnchantment() API method
api3/blocks users: I am sorry I kept you waiting so long
2017-10-09 11:40:53 +01:00
9598b8cee4 Use API methods instead of directly setting properties 2017-10-09 11:38:52 +01:00
246c6daef6 how irritating 2017-10-09 11:30:11 +01:00
2601e35990 Cleaned up and added API for entity air supply, fixed oxygen being used in creative/spectator
this commit also includes respiration checks because it's cherry-picked
from api3/blocks, but respiration won't work until it's registered.
2017-10-09 11:28:40 +01:00
bdfd9c95dd Minor cleanup to attack handler 2017-10-09 11:02:00 +01:00
cd44551d64 Cleaned up checks for handling inventory transactions 2017-10-09 10:57:28 +01:00
cebb4b35f6 Fixed beds not getting deleted properly in survival
the anti-instabreak kicked in twice... damned anti-cheat... luckily the player is not needed for this part
2017-10-09 10:49:30 +01:00
7267f1a520 Fixed some usages of Item constants for Blocks
only cosmetic change
2017-10-09 10:37:19 +01:00
66a3354b31 Fixed not respawning adjacent tiles correctly when cancelling block break events 2017-10-09 10:30:48 +01:00
ac7384a2b4 Re-organise some Player methods
- group spawn-related methods
- group achievement-related methods
- move isSleeping()
- group name-related methods
- move Player->sendAllInventories()
- move Player->jump()
2017-10-09 10:25:33 +01:00
748beaaaa7 Changed a couple of very misleading default values
why on earth did I do this
2017-10-09 09:55:18 +01:00
58788b4bc7 Removed some unnecessary stuff PhpStorm complained about 2017-10-09 09:46:21 +01:00
ae76ac82c8 Removed unnecessary delegate packet handlers
let's keep all the TODOs in one place
2017-10-09 09:44:22 +01:00
e4000f8f03 Reorganise some packet methods in Player 2017-10-09 09:35:31 +01:00
ebcce43131 Don't hold player references for hiddenPlayers
they aren't needed, and this is just one more thing that could go wrong in Player->close() that could lead to leaks.
2017-10-09 09:20:44 +01:00
119913da30 Modified misleading comment (#1455)
The plugin isn't supposed to extend PluginTask, the task is
2017-10-09 07:52:40 +01:00
1a88f59b23 Moved some stuff from join to login
this is how it should be
2017-10-08 19:38:03 +01:00
fdfe70b9f2 Removed entity metadata setting from LoginPacket handler
why the f was this here
2017-10-08 19:10:49 +01:00
3bda1473e7 Removed outdated documentation for Player->getClientId() 2017-10-08 18:47:13 +01:00
29cd071108 Added some documentation on player UUIDs 2017-10-08 18:40:27 +01:00
1810088acf Use Player->isCreative() 2017-10-08 18:17:12 +01:00
51e4a62e7b Use setUsingItem() instead of directly setting data flags 2017-10-08 18:03:19 +01:00
aa91183504 Added Durable class, fixed some tools not breaking correctly, removed some boilerplate code 2017-10-08 15:54:31 +01:00
ae5aa31e7b Add Item->setNamedTagEntry() and Item->removeNamedTagEntry() 2017-10-08 15:06:30 +01:00
7239dbbb1a Merge remote-tracking branch 'origin/pr/1453' 2017-10-08 14:20:02 +01:00
3738ab1f8a Fixed villager professions being useless 2017-10-08 14:14:42 +01:00
8fafef2f7f Added tagType parameter to ListTag constructor, remove some boilerplate code 2017-10-08 13:28:01 +01:00
5b9515b20f Peaceful difficulty allows PvP 2017-10-08 13:57:25 +02:00
69e29236aa Remove some redundant code for checking existence of creative items
getCreativeItemIndex() does basically the same thing anyway
2017-10-08 12:50:53 +01:00
e8453b7872 Item->getNamedTag() now always returns a CompoundTag object, removed lots of boilerplate code
This change resulted from many complaints and ugly boilerplate code because getNamedTag() is only ever used when you want to read from the tag or modify it. If you have code that depends on this returning null, you should use hasCompoundTag() instead.
2017-10-08 12:41:57 +01:00
00bf190e54 Make Item->getNamedTag() a bit less ugly 2017-10-08 12:17:18 +01:00
81dee2f9fc Adding writable and written books. (#1397)
* Adding writable and written books.
* Added a PlayerEditBookEvent.
* Changed BookEditPacket field names.
2017-10-08 11:49:57 +01:00
f6875705a1 Found fields of PhotoTransferPacket
now if we could only get portfolios...
2017-10-08 11:25:27 +01:00
d294d5a91b Clarified location table doc for RegionLoader 2017-10-06 09:40:46 +01:00
a7e9aa4bc1 Fixed falling sand replacing wrong blocks when moved slightly by currents 2017-10-05 17:38:32 -04:00
628ff9449e Fixed respawn fall damage when dying while falling from causes other than fall damage
tl;dr: fall distance didn't get reset
2017-10-05 16:47:50 -04:00
7f5fe137d1 Added some type docs to RegionLoader 2017-10-05 18:47:32 +01:00
18448cbcb8 Fixed several bugs with statistics updating and resetting
- fixed ridiculous network stats when title ticker or console colours are disabled (shoghicp, what fit of madness led you to think this was a good idea)
- fixed network stats reporting kb/16ticks instead of kb/s
- fixed TPS reporting getting reset after 16 ticks instead of 20
- title ticker and MOTD is now updated every 20 ticks instead of 16
2017-10-05 16:48:50 +01:00
b0104099fe Add a couple of comments to pocketmine.yml to clarify settings usage 2017-10-04 14:44:52 +01:00
68195c64ce Remove dead COMPRESSION_LEVEL property from Level 2017-10-04 14:26:04 +01:00
27aa51bac4 Added some type docs to Level 2017-10-04 14:25:06 +01:00
eac1d76e8b Fixed Level->stopTime not being set 2017-10-04 14:08:23 +01:00
a8c6e14d02 Chunk cache is now non-optional, close #1448 2017-10-04 13:50:32 +01:00
bf68a6a9fc Fixed canUseChunkCache() logic (#1446)
Fix setting disable chunk cache on low memory being useless, fix chunk cache not working if low memory cache clear is enabled
2017-10-03 20:27:53 +01:00
4dfd171af0 Add flint-steel light sound, close #1434 2017-10-03 19:39:01 +01:00
fc9c264e77 Resend blocks around targeted blocks when interactions & block-break are cancelled, fixes #906
this solution is dumber but more effective (also solves the beds & doors placement problem)
2017-10-03 19:28:01 +01:00
04ba41c58c Remove redundant properties from recipes.json
- we don't use the UUIDs, and they change every time, this just pollutes the diffs and makes my contribs ridiculous
- we don't need the height/width of shaped recipes because the generated shape tells us what it is
2017-10-03 17:30:26 +01:00
736cc927ff Enable chunk caching by default
the footprint of compressed chunk batches is so small now that it doesn't make sense to disable it out of the box. The performance gains from caching chunks are more than worth it.
As of 1.2, the average footprint of these caches is usually ~2% or less of the size of the actual chunk itself. Moving around a lot will frequently cause the same chunks to get sent several times as it passes in and out of your render distance, and the chunk isn't even changing in that time, so the chunk is getting needlessly re-serialized over and over again. So even if your world is not static (for example a creative server) chunk caching will still offer benefits, and the memory expense is so small it's a no-brainer.
2017-10-03 13:16:30 +01:00
4be7885ee4 Remove redundant assignment in Level constructor 2017-10-03 12:57:30 +01:00
7dc5dc3a9f Restrict item meta values to max signed short value, closes #1101 2017-10-03 12:35:08 +01:00
f7ee78233b Item IDs should always be unsigned, treat them with appropriate measures (fixes #1376) 2017-10-03 12:28:50 +01:00
88807e8b22 Fixed Binary::unsignShort() being non-static 2017-10-03 12:21:09 +01:00
5a6812357b imports 2017-10-03 11:34:41 +01:00
ca401ec3f5 Force-close the crafting window only when doing crafting transactions
otherwise the client will crash when using right-click on the recipe book
2017-10-03 11:33:09 +01:00
9bbebaa071 Force-close the inventory window when crafting fails to avoid desync issues
mojang, why does this have to be hard work
2017-10-03 11:04:21 +01:00
76117e7fa0 Get XUID from LoginPacket after authentication, add Player->getXuid() 2017-10-02 18:51:51 +01:00
088a44ea3a Fixed bug reading pubkey from LoginPacket
this isn't part of extraData
2017-10-02 18:05:50 +01:00
b54f256fea Added a hack to cut down on excess skin geometry bloat
there are further ways this can be debloated, but non-pretty-printing it cuts the size down by ~70-80%.
2017-10-01 16:50:16 +01:00
c09d782503 Fix #145, take 2 (slab placement in half gaps doesn't work) (#1411) 2017-10-01 16:19:59 +01:00
b3b3ee7c56 Use transparent skin on FloatingTextParticle 2017-10-01 14:10:47 +01:00
ab5bbaa7bd Remove redundant property from Player 2017-10-01 12:19:11 +01:00
afa37bd2aa check range of valid compression values
zero is not allowed because it's pointless, just raise your compression threshold if you want zero compression.

Chunks will always be compressed regardless of threshold because they are huge. It doesn't make sense to allow uncompressed chunks when even compression level 1 will reduce their size 50x. The point of the last two (reverted) commits was to prevent compression level zero being used on chunks. Probably obvious that I was up late and not thinking very clearly.

Revert "Reduced chunk compression level to 7"

This reverts commit 49ac2555ce.

Revert "Always use best compression for chunks"

This reverts commit 42dd9d6abd.
2017-10-01 11:06:14 +01:00
49ac2555ce Reduced chunk compression level to 7
According to benchmarks 8 and 9 are simply orders of magnitude slower while not saving enough bytes to make it worth the performance loss. 7 is a good balance.
2017-10-01 09:20:14 +01:00
edd0189d59 Some improvements to issue template 2017-09-30 21:19:38 +01:00
b76b9d53fe Fixed drops for DeadBush 2017-09-30 21:04:39 +01:00
42dd9d6abd Always use best compression for chunks 2017-09-30 20:30:24 +01:00
9cd7f39c03 Fixed typo on ProjectileItem class (#1431) 2017-09-30 16:17:22 +01:00
f6e30d4225 s/online-mode/xbox-auth/
lots of servers are currently running in insecure mode without realizing because of old Genisys shit configs?!
2017-09-30 12:19:24 +01:00
27798c69ee fix collision detection not detecting fence & fence-gate, fixed nether-brick fence gate AABB, close #1299 2017-09-29 15:27:14 +01:00
a33be643c4 Fixed falling blocks not falling when placed above fire, close #1425
yes, hardcoding this is not a nice solution - PC also does this, want to fight?
2017-09-29 14:53:23 +01:00
a06ff3d96b Revert "Fixed falling blocks glitching when spawned"
This reverts commit 827ee5d4f9.

can't ever seem to get falling blocks right... should I blame mojang?
2017-09-29 14:22:03 +01:00
e6cecabf3f New skin API, add support for custom capes & custom geometry (#1416)
* Added support for changing skins ingame, custom capes & geometry
* Use PlayerSkinPacket for setting Human skin instead of PlayerList hack
2017-09-29 14:09:00 +01:00
c273a46537 Ditch crafting transaction if we get normal inventory action with incomplete crafting transaction 2017-09-28 20:07:07 +01:00
c448f4a3b5 Added handling for reflected ShapedRecipe crafting, close #1415 2017-09-28 18:45:22 +01:00
86b76bfcab Fixed trying to get pubkey that doesn't exist in VerifyLoginTask
bug was exposed by previous commit
2017-09-28 18:14:53 +01:00
7ba193dc2e Set ErrorException handler on AsyncWorkers 2017-09-28 18:01:31 +01:00
f565791e41 World loading: Actually use the data in each item instead of getProperty() 2017-09-28 16:38:10 +01:00
bc0434913e Fixed crash when a numeric world seed is set in pocketmine.yml 2017-09-28 16:35:19 +01:00
9bc8d8db79 Revert "Add buffering for non-immediate priority packets to reduce compression overhead"
This reverts commit 2162675b64.

This broke Human skins... it seems MCPE doesn't like you adding and
removing a player from the list in the same batch.
2017-09-28 14:29:17 +01:00
d0bf0ff083 Imports cleanup 2017-09-28 10:51:05 +01:00
7dc1fc54b1 Oops, didn't mean to commit this 2017-09-27 20:34:37 +01:00
bae42dc0d9 Fixed incorrect field names in PlayerSkinPacket 2017-09-27 17:55:04 +01:00
ab809f8a2b Updated RakLib submodule 2017-09-27 15:53:43 +01:00
2162675b64 Add buffering for non-immediate priority packets to reduce compression overhead 2017-09-27 14:06:42 +01:00
8f63117dac Use try...finally in Player->sendDataPacket() so we don't forget to stop timings 2017-09-27 13:52:25 +01:00
1c9b4f3e21 Fixed ItemBlocks retaining Level references after being placed, close #1395 2017-09-27 12:04:56 +01:00
48d2d7e422 Remove unused import from FoodSource 2017-09-27 12:01:55 +01:00
52bd042bde BaseInventory: Don't keep calling getSize() over and over and over again 2017-09-27 11:24:21 +01:00
4b63a22f8c More use of Item->isNull() 2017-09-27 11:05:40 +01:00
c47f1f572c Added API method Item->pop() 2017-09-27 10:56:04 +01:00
7a77bb0402 Login verification: guilty until proven innocent
assume it's invalid until we've verified everything
2017-09-27 10:29:01 +01:00
90cb018de2 Re-organise some Block code 2017-09-26 19:39:05 +01:00
992c4ce6a0 Added API method Block->getVariant() 2017-09-26 19:35:04 +01:00
78af87a572 ConcretePowder: add tool type 2017-09-26 19:00:53 +01:00
c79a5509f6 Implemented concrete powder
this is a little buggy with water updating due to a hack for liquids to fix a CPU leak (210bdc2436), but everything works fine when a block nearby gets updated.
2017-09-26 18:56:43 +01:00
827ee5d4f9 Fixed falling blocks glitching when spawned
this now (finally) works flawlessly
2017-09-26 18:33:34 +01:00
f5b0cbb337 Generated some TODOs for BlockFactory & ItemFactory 2017-09-26 16:15:35 +01:00
18777a9041 Remove useless EntityEventPacket
vanilla doesn't send this, and it doesn't do anything if we _do_ send it.
2017-09-26 12:50:36 +01:00
13d50aff62 don't break bows, stupid 2017-09-26 12:20:40 +01:00
5b191327bc Fixed players' arms staying stuck up after eating something 2017-09-26 12:14:10 +01:00
8811188e71 Split FoodSource up into two interfaces 2017-09-26 11:48:47 +01:00
38fad4b963 Implement difficulty per-world (#878)
* Moved Server::getDifficultyFromString() to Level
* Added ability to set difficulty in worlds section of pocketmine.yml for generation
2017-09-26 11:16:51 +01:00
e64076ec81 Disconnect 1.1 clients properly (HACK!) 2017-09-26 10:01:32 +01:00
ccbdb77618 Cleaned up LoginPacket handling, don't nuke the buffer 2017-09-26 09:49:35 +01:00
91c6086ae1 Updated PocketMine-Language submodule 2017-09-26 09:35:43 +01:00
85ec7d9732 Change default MOTD
"Minecraft: PE Server" is no longer accurate, "Minecraft: Bedrock
Edition Server" is too wordy, and "Minecraft: BE Server" just sounds
weird.

and I'm not calling it simply a "Minecraft Server"
2017-09-25 23:43:09 +01:00
10f597cd64 Stop hardcoding "PocketMine-MP" everywhere 2017-09-25 18:17:35 +01:00
6e5759b1d1 Made incompatible client disconnect messages more informative 2017-09-25 14:30:11 +01:00
03d3e595d6 Implement JWT signature verification and Xbox Live checks, close #315
This can be enabled or disabled using the "online-mode" directive in
server.properties.

NOTE: For safety reasons it is enabled by default, since many naive server owners currently believe that authentication is not needed because "the client is forced to sign-in".
Newsflash for readers: the forced authentication is easily bypassed using a LAN proxy.

Un-authenticated LAN connections will still work fine if the online mode is disabled.

Added the following API methods:
- Server->getOnlineMode() : bool
- Server->requiresAuthentication() : bool
- Player->isAuthenticated() : bool

JWT verification is rather expensive, so it is done in an AsyncTask. Make sure you don't hog your worker threads.
2017-09-25 12:30:58 +01:00
8ca59d12e9 Updated PocketMine-Language submodule 2017-09-25 11:36:39 +01:00
89e4defa29 use null coalesce in Server->getLevel() 2017-09-25 09:51:21 +01:00
f5534a9ab0 Server: add some typehints 2017-09-25 09:49:19 +01:00
28bce8d48c Fixed plugins causing crashes by using Level->unload() and add a warning
yes, we don't want you to use this, but it still shouldn't crash if it can be prevented...
2017-09-25 09:46:19 +01:00
3c02a6a8ed Fixed eating sounds 2017-09-24 21:18:08 +01:00
6b0ac8adb8 Don't overwrite the input map with reindexed stuff
we might need this again?
2017-09-24 19:17:00 +01:00
38ec5da260 Refactored API compatibility checking code into its own method (#1394)
Refactored API compatibility checking code into its own method so plugins can use it
this change was inspired by https://github.com/poggit/devirion/blob/master/src/poggit/virion/devirion/DEVirion.php#L140-L172
2017-09-24 15:00:08 +01:00
240cc3043a Rewritten crafting, fixed #45 2017-09-24 14:14:24 +01:00
043ae487de Fixed some inconsistent uses of new ShortTag vs setValue() in Furnace 2017-09-24 10:34:25 +01:00
f12701e582 Fixed possible undefined NBT in Furnace, close #1398 2017-09-24 10:29:36 +01:00
6e961ae897 Addition of Coarse Dirt (#1396) 2017-09-23 22:25:03 +01:00
e1d10f595a AdventureSettingsPacket: removed leftover TODO comment 2017-09-23 16:51:58 +01:00
178dd1b981 Fixed block picking, added PlayerBlockPickEvent 2017-09-23 14:42:28 +01:00
826ec90856 Revert "Workaround for some plugins crashing clients during PlayerLoginEvent"
This reverts commit 087a994393.
2017-09-23 13:23:19 +01:00
0523f26613 Send forced movement when getting bad movements after teleport, fixes AlwaysSpawn-type plugins
it's mostly harmless to send it here anyway
2017-09-23 12:49:46 +01:00
5190d9c1e2 Fixed possible issue with JWT decoding
this is url-encoded, these characters should be replaced before base64_decode()ing. Not sure how this didn't get noticed before now.
2017-09-22 19:52:08 +01:00
c8fd0eaf8b Removed autogenerated stub TODO from BoneBlock 2017-09-21 19:50:03 +01:00
53ef9b653a Added some getters to FloatingTextParticle 2017-09-21 19:10:30 +01:00
030cc4afb0 FloatingTextParticle: import cleanup & typehints 2017-09-21 19:09:33 +01:00
9bd7f771d3 "Fixed" FloatingTextParticle yet again
- nametag visibility flags don't work properly, only players show them all the time
- invisibility overrides nametag visibility
- scale 0 triggers asserts on debug builds

..... how hard is it to NOT break these simple things each update Mojang?

closes #1205
2017-09-21 19:04:45 +01:00
10f6a0eef0 FloatingTextParticle: fixed incorrect parameter type doc 2017-09-21 18:31:12 +01:00
d0a96f35da ./ hack is back (/help is client-side >_<) 2017-09-21 17:51:39 +01:00
65e908a403 Move Travis Test server files into a separate directory
this is for convenience locally running Travis Test so my existing data doesn't interfere
2017-09-21 17:16:27 +01:00
d7091f4460 Fixed not being able to disable stats reporting using command line options 2017-09-21 17:14:44 +01:00
c6670b2e74 Fixed Nether Wart's name 2017-09-21 16:56:41 +01:00
194278d986 Updated TesterPlugin submodule 2017-09-21 16:56:27 +01:00
0e2e9aab2e Fixed crash when block classes override the constructor but don't specify a fallback name 2017-09-21 16:43:33 +01:00
1b5fed983b Revert "Fixed slab placement, close #145", reopen #145, close #1314
This reverts commit f2ff0198cc.
2017-09-21 14:41:18 +01:00
5aba87b250 Added brown and red mushroom blocks 2017-09-21 14:07:51 +01:00
f01ce8e994 null and void typehints 2017-09-21 12:54:04 +01:00
d89b8cf12e Clean up SlotChangeAction inventory handling 2017-09-21 12:44:03 +01:00
6aa9b081e9 Cleanup unused imports 2017-09-21 12:26:41 +01:00
dbed80386a Removed redundant interface 2017-09-21 12:22:47 +01:00
cefad0444c Merge branch 'master' into mcpe-1.2 2017-09-21 10:32:35 +01:00
ee052f91d4 Fixed some air items with count 1 instead of 0 2017-09-21 10:30:14 +01:00
ef6250967f Use Item->isNull() more 2017-09-21 10:29:29 +01:00
61cfdac6a1 Fixed a mistake in entity attack handler 2017-09-21 10:18:52 +01:00
fd7fb10223 Return null on unmatched inventory action and log details 2017-09-20 18:38:14 +01:00
6897cb4774 Moved inventory action magic slot constants where they belong 2017-09-20 18:27:29 +01:00
8e7ad532f1 Updated RakLib submodule 2017-09-20 18:16:41 +01:00
9e8366725a Bump for 1.2.0.81 2017-09-20 17:30:27 +01:00
b14ecc18c4 Remove unused imports 2017-09-20 12:24:44 +01:00
55720d9f0a Added InventoryAction->onPreExecute(), fixed PlayerDropItemEvent deleting items 2017-09-20 12:19:42 +01:00
0262465a26 Fixed dupe cake glitch
this is what happens when you try to be clever when not properly awake
2017-09-20 11:19:15 +01:00
7996a7b08c Testing handling multiple result items for ShapedRecipes
this doesn't work yet, I wanted to see how glitchy it is with cakes. The answer is: very glitchy.
2017-09-20 11:14:09 +01:00
4a1fc1bdf7 don't try to send contents during inventory construction 2017-09-20 10:18:24 +01:00
85b2b2ae2e Don't send tile inventory slots during the constructor
This is completely pointless and a waste of time.
2017-09-20 10:15:28 +01:00
38e11aae5e Some cleanup to how EntityInventoryChangeEvents are handled 2017-09-20 10:13:05 +01:00
f0755d1659 Fixed handling of recipes that require a crafting table 2017-09-20 09:43:49 +01:00
fd33a65e3b Small cleanup of recipe UUID handling (furnace recipes don't need UUIDs) 2017-09-20 09:34:00 +01:00
7baadf9dad Throw updated pthreads at Travis 2017-09-19 20:49:41 +01:00
ca23864e4c CraftingManager: use null coalesce for matching furnace recipes 2017-09-19 20:03:21 +01:00
8728547a11 Remove unused imports 2017-09-19 19:58:53 +01:00
90fb3c5e12 Moved getNetworkType() to ContainerInventory since it's not used anywhere else 2017-09-19 19:57:22 +01:00
1fb6d12a6b Add getInventory() to Container interface where it's actually useful 2017-09-19 19:26:41 +01:00
1323d89139 Remove redundant duplicated code for sendContents() and sendSlot() 2017-09-19 19:07:12 +01:00
136ab1dba1 Inventory->getItem(): Removed useless clones
this already returns a copy of the item anyway... wtf?
2017-09-19 18:49:08 +01:00
8cae20e818 Removed hotbar slot linking (works like PC now) 2017-09-19 18:36:57 +01:00
ff2b3bfa2a SimpleCommandMap: remove some dupe and arrange commands alphabetically 2017-09-18 18:43:06 +01:00
361b262d3a Merge branch 'master' into mcpe-1.2 2017-09-18 10:29:38 +01:00
1fd7f441b4 Travis: use older version of pthreads
master is broken - https://github.com/krakjoe/pthreads/issues/757
2017-09-18 10:20:15 +01:00
3f56d6ddc8 RakLibInterface: removed useless needACK condition 2017-09-18 09:42:25 +01:00
1e4cbb0dd9 RakLibInterface: move array initialization to default value
doesn't make sense to do this in the ctor when all the others are normal
2017-09-18 09:34:00 +01:00
a99eee9def Removed redundant assignment 2017-09-17 20:01:11 +01:00
bdee746e46 Automatically enable ANSI colours on Windows versions that support it
Note that stream_isatty() and sapi_windows_vt100_support() are ONLY defined on PHP 7.2, and the latter is only available on Windows.
2017-09-17 19:57:20 +01:00
642c7733cd Cleaned up ShapedRecipe handling, ShapedRecipe API changes
use shapes from json instead of just generating maps
fix a ton of bugs
2017-09-17 11:45:16 +01:00
c8199e14ad Removed redundant duplicate method call 2017-09-16 23:09:14 +01:00
0f37bc35ba Always evacuate the crafting grid on close, no matter whether it's big or not
otherwise items will get deleted and people will cry
2017-09-16 21:58:10 +01:00
8dc3d019f6 Return handled on fake window close 2017-09-16 21:55:25 +01:00
bd64172750 Added API method Item->equalsExact() and removed some boilerplate code 2017-09-15 16:48:46 +01:00
0e51820dfb Merge remote-tracking branch 'origin/master' into mcpe-1.2 2017-09-15 15:54:30 +01:00
30d2318bb7 Merge pull request #1383 from pmmp/quoted-command-args
Quoted command args & allow playernames with spaces
2017-09-15 14:04:48 +01:00
63634d7e7d Added compaction and sorting for repeated slot changes in a single transaction
Now items should be able to move around the crafting grid correctly.
2017-09-15 13:32:17 +01:00
d941bf8e74 Add vanilla-style crafting grid item evacuation server-side when closing the window in case something goes wrong 2017-09-15 13:22:53 +01:00
8c9d9626ab Merge branch 'new-pack-codes' 2017-09-14 19:53:07 +01:00
6b34c47c96 Merge branch 'master' into mcpe-1.2 2017-09-14 18:16:45 +01:00
77241e14ce Bumped to ALPHA8 to account for AsyncTask API changes 2017-09-14 17:49:12 +01:00
15b08c1417 Added capability to dump AsyncWorkers' memory (#1379)
This now actually works with PHP 7.2 + latest pthreads, before it was too unstable.
2017-09-14 16:45:48 +01:00
4d1daecd91 oops! 2017-09-14 11:01:47 +01:00
53e5db5142 Updated PreProcessor submodule 2017-09-14 10:58:46 +01:00
ad72fe6232 Make use of awesome new pack() codes for floats 2017-09-14 10:41:53 +01:00
8b33f711d0 Allow spaces in player names 2017-09-14 10:15:35 +01:00
319735db3a Add support for quoting command arguments
Un-escape quotes in inputted strings
2017-09-14 10:15:30 +01:00
c283d87494 Some minor cleanup of PocketMine.php 2017-09-13 19:14:31 +01:00
be27e03126 Some minor AutoUpdater cleanup, stop hardcoding everything 2017-09-13 18:51:06 +01:00
c1c290cd39 Beware matching items that aren't actually correct
This would only ever happen if we received the actions in the wrong order, but that wouldn't surprise me.
2017-09-13 11:37:10 +01:00
5267c571e9 add handling for -100 fake source type (evacuate crafting table contents) 2017-09-13 11:15:31 +01:00
0fac3b9a9d Added encode for InventoryTransactionPacket and refactor some stuff 2017-09-13 11:14:04 +01:00
23a38400e2 Added CraftingGrid and BigCraftingGrid, WIP stuff for crafting
moving whole stacks in & out of the crafting grid works now, splitting stacks is fucked up because the transaction system can't handle the same slot changing multiple times in one transaction
2017-09-12 19:34:06 +01:00
297172d111 Send creative inventory for all gamemodes, fixed recipe book 2017-09-12 14:40:16 +01:00
825d4f9702 Location cleanup (#1380)
There's no sense rewriting code that the parent constructor already implements.
2017-09-12 12:18:35 +01:00
1d31958ce6 Updated preprocessor submodule 2017-09-12 09:12:38 +01:00
130a60f2b2 Fixed ItemFactory::isRegistered() returns false for blocks 2017-09-11 18:23:26 +01:00
07268e4b37 Added API methods to determine if a block or item is already registered 2017-09-11 16:22:55 +01:00
441efc4ae2 Merge branch 'master' into mcpe-1.2 2017-09-11 14:40:25 +01:00
88bd7713c5 Fix preprocessor 2017-09-11 09:42:31 +01:00
aaa3b6e59a Added explicit AsyncTask->storeLocal(), removed AsyncTask->__construct() object storage (#1322)
Far too often I see people using IDEs which generate the constructors for them and then accidentally unintentionally store things in the object store. This parent constructor behaviour is unexpected. If a developer wants to store something, they should now do so explicitly by calling storeLocal().
2017-09-10 20:31:28 +01:00
25adac8859 Added support for Composer (#323) 2017-09-10 19:23:34 +01:00
8d0b881762 fixed command arg types 2017-09-10 13:56:34 +01:00
16cb75ef38 Merge branch 'master' into mcpe-1.2 2017-09-09 21:58:30 +01:00
3b9689674d Merge remote-tracking branch 'origin/php/7.0' 2017-09-09 21:57:44 +01:00
7f5d8cc900 Always log stack traces regardless of whether log-debug is enabled 2017-09-09 19:27:26 +01:00
8761256246 Be more clear about WHY not to use source installs in production 2017-09-09 19:21:32 +01:00
8c363cb571 Added capability to specify arguments to PocketMine.php when running start.ps1
Example: .\start.ps1 --disable-ansi --debug.level=2
2017-09-09 18:44:18 +01:00
10b765e17a Merge branch 'php/7.0' into mcpe-1.2 2017-09-09 18:08:47 +01:00
0eb866bf25 Updated AvailableCommandsPacket 2017-09-09 14:23:19 +01:00
c46caa38e1 merge 2017-09-09 11:33:00 +01:00
17d949f476 Fixed SPL being reported as incompatible when it's actually not found 2017-09-09 11:25:59 +01:00
c569f55933 Fixed can't find sources when PocketMine.php is run from anywhere other than the repository root 2017-09-09 11:22:56 +01:00
01d8d216ca Yet another merge commit 2017-09-09 00:53:03 +01:00
f1ccee505b Submodule update (this is getting annoying) 2017-09-09 00:51:20 +01:00
a61adb5991 Merge branch 'php/7.0' 2017-09-08 21:40:25 +01:00
cae1a3bb4b Updated DevTools submodule 2017-09-08 21:38:14 +01:00
6681bd250a Merge branch 'php/7.0' 2017-09-08 20:37:09 +01:00
38293913ee Updated DevTools submodule 2017-09-08 20:36:32 +01:00
8493ce8a35 Merge branch 'php/7.0' 2017-09-07 20:07:16 +01:00
9b7868238c Improved Travis Test, capture error output from console, test phar 2017-09-07 20:03:58 +01:00
953c1ef4ec Fixed formatting issues in Travis test script 2017-09-07 20:03:54 +01:00
021a9a4820 Merge branch 'php/7.0' 2017-09-07 19:33:01 +01:00
5b7565664c Removed WeakRef from Travis CI 2017-09-07 19:32:04 +01:00
ebdfbe6bb9 Removed flight controls hack for spectator mode
THEY FINALLY FIXED IT
2017-09-07 19:06:36 +01:00
85ff236461 Fixed formatting issues in Travis test script 2017-09-07 17:27:07 +01:00
d7422d9283 Updated for 1.2.0.31 beta 2017-09-07 10:50:53 +01:00
fcb3c4820e Merge branch 'php/7.0' into mcpe-1.2 2017-09-07 10:42:20 +01:00
c72ef605b9 Fixed server crash when a garbage timezone value is set in php.ini, fallback to auto-detection 2017-09-07 10:40:32 +01:00
e274f1b7f8 Merge branch 'php/7.0' 2017-09-06 17:54:50 +01:00
69514c5763 Submodule update: Fixes little-endian longs being written in the wrong order, closes #1358 2017-09-06 17:54:38 +01:00
12c154badf Merge branch 'php/7.0' 2017-09-05 20:06:02 +01:00
c9ee206fe6 Merge branch 'php/7.0' 2017-09-04 19:42:03 +01:00
6877ac35eb Merge branch 'php/7.0' 2017-09-04 10:01:47 +01:00
78d49f8e66 Merge branch 'php/7.0' into mcpe-1.2 2017-09-03 15:02:41 +01:00
de6ebc5791 Merge branch 'php/7.0' 2017-09-03 15:00:29 +01:00
2cff5a500c Merge branch 'php/7.0' 2017-09-02 19:05:27 +01:00
f077ba4748 Merge branch 'php/7.0' into mcpe-1.2 2017-09-02 19:05:18 +01:00
dcf34b7188 Merge branch 'php/7.0' 2017-09-02 18:57:49 +01:00
ca84532640 Merge branch 'php/7.0' into mcpe-1.2 2017-09-02 18:57:39 +01:00
75e32b11b7 Merge branch 'php/7.0' into mcpe-1.2 2017-09-02 18:29:53 +01:00
9f44b2ed75 fixing ClientboundMapItemDataPacket 2017-09-02 18:22:53 +01:00
1c02c747ca Merge branch 'php/7.0' 2017-09-02 13:13:54 +01:00
a6c0f1512c Send the hotbar instead of contents when resetting hotbar
This used to be fine before 1.2, but now hotbar is handled separately.
2017-09-02 11:07:14 +01:00
604d8ecf9a Protocol changes for 1.2.0.25 2017-09-02 11:05:49 +01:00
5d75d3d5b6 Merge branch 'php/7.0' into mcpe-1.2 2017-09-01 23:10:58 +01:00
8b13b520e0 Merge branch 'php/7.0' 2017-09-01 20:22:25 +01:00
00e4fff259 Fixed Item fromString() crash on PHP 7.2 2017-09-01 20:05:04 +01:00
a06c934f4d Merge branch 'php/7.0' 2017-09-01 19:37:27 +01:00
5335ed9394 Merge branch 'php/7.0' 2017-09-01 16:57:51 +01:00
16aeb0ac85 Update .travis.yml 2017-08-31 21:12:45 +01:00
8caabd3267 Check for existence of ChunkUtils extension 2017-08-31 21:04:36 +01:00
ddfe828445 Require PHP 7.2, bump PocketMine-MP version to 1.7dev 2017-08-31 20:27:05 +01:00
67ad2d25b9 Added FireImmune data flag 2017-08-30 18:36:36 +01:00
190f4dd6ab New entity metadata flags 2017-08-30 14:13:24 +01:00
6d6283b7f3 Fixed Player->sendPosition() not working correctly 2017-08-28 20:07:04 +01:00
a3d21de559 Cleaned up network inventory action reading and core action creation 2017-08-28 20:04:35 +01:00
ece0692229 Fixed UUID corruption in recipe data
this is important for MultiRecipes to work correctly (yes I know we don't use these yet!)
2017-08-28 18:04:11 +01:00
b5d2402c9b Merge branch 'master' into mcpe-1.2 2017-08-28 18:02:09 +01:00
c7fd3eb725 Merge branch 'master' into mcpe-1.2 2017-08-27 16:09:23 +01:00
5433a3f964 Merge branch 'master' into mcpe-1.2 2017-08-24 19:26:52 +01:00
2c3d7c49f9 Updated creative inventory data with new item json serialization (more compact) 2017-08-24 12:17:17 +01:00
76acb1da7b New crafting recipe data format, more readable & more compact 2017-08-24 12:05:35 +01:00
17518195d1 Be more smart about json-serializing items
Don't include nbt_hex if we don't have a NBT tag
Don't include damage unless it's non-zero
Don't include count unless it's non-1
2017-08-24 12:02:03 +01:00
2443a57234 Merge branch 'master' into mcpe-1.2 2017-08-24 11:57:41 +01:00
95752ef542 Merge branch 'master' into mcpe-1.2 2017-08-23 13:20:35 +01:00
da4c9cf404 Fixed inventory cyclic references causing players to not get garbage-collected 2017-08-23 13:13:15 +01:00
770616d4ab Merge branch 'master' into mcpe-1.2 2017-08-22 20:48:32 +01:00
445a67954d Merge changes from master 2017-08-22 14:13:31 +01:00
4250e99e3a Updated for 1.2.0.22 2017-08-22 11:35:56 +01:00
121777375e Rewired eating 2017-08-21 12:52:20 +01:00
93e149e91c Rewiring release-item action to fix bows 2017-08-20 22:14:31 +01:00
1f70a7830e Branch merge 2017-08-20 21:07:19 +01:00
159b2e3d5e Merge branch 'master' into mcpe-1.2 2017-08-19 21:42:33 +01:00
e0307411da Cleaned up PlayerList handling 2017-08-19 19:36:15 +01:00
e5e76d4c93 Merge branch 'master' into mcpe-1.2 2017-08-18 18:39:39 +01:00
2688228a6f Don't dump subchunk raw data 2017-08-18 16:57:07 +01:00
e15eefc58f ... 2017-08-18 13:58:33 +01:00
8853452feb Updated for 1.2.0.18 2017-08-18 12:36:04 +01:00
09c53552c1 Merge branch 'master' into mcpe-1.2 2017-08-18 08:29:40 +01:00
1f6d325328 Added API for assigning permanent windows, fixed teleportation breaking inventory 2017-08-17 19:43:59 +01:00
f35ca147bb Merge branch 'master' into mcpe-1.2 2017-08-17 18:38:30 +01:00
b6fb2bca13 forgot to add this to the merge 2017-08-17 17:27:49 +01:00
4f1302adf2 Merge branch 'master' into mcpe-1.2 2017-08-17 17:14:16 +01:00
643e10037c Merge branch 'master' into mcpe-1.2 2017-08-16 13:19:37 +01:00
eda2473e78 New LevelEventPacket constants 2017-08-16 12:53:53 +01:00
4b65fef957 Fixed LevelEvent broadcasting 2017-08-16 12:53:32 +01:00
fbe2567e58 Merge branch 'master' into mcpe-1.2 2017-08-16 12:31:12 +01:00
5fc50aeda5 Found an unknown field in StartGamePacket 2017-08-16 10:10:42 +01:00
9be1b929a5 Added PhpDoc for packet field types and changed float x,y,z to Vector3 2017-08-13 20:02:07 +01:00
6480f7a989 Found an unknown field in TextPacket and added some docs 2017-08-13 18:20:06 +01:00
1576a79644 more packets 2017-08-13 17:43:33 +01:00
02cbf800d0 Added encode/decode for ModalFormResponsePacket 2017-08-12 19:33:16 +01:00
5a4fbc6f5a Handle exception for crafting and resend inventories 2017-08-12 19:11:57 +01:00
83fcec3e94 Don't add actions to the transaction if a crash occurred when getting the source inventory 2017-08-12 14:29:12 +01:00
5d436a06ec Added a method to get player cursor inventory 2017-08-12 14:10:47 +01:00
8958b3c51c Many many changes related to inventory transactions, fixed item dropping, fixed creative menu 2017-08-11 19:57:30 +01:00
c1ff7bbef4 Added creative-inventory magic slot numbers and renamed some constants 2017-08-11 12:31:11 +01:00
74ee94b385 Duct tape for inventory transactions, removed ContainerSetSlotPacket 2017-08-10 20:05:15 +01:00
5208ad885c Added crafting use-ingredient fake transaction source 2017-08-10 18:42:14 +01:00
51be88c698 Fixed AdventureSettings not working 2017-08-10 13:01:20 +01:00
0dc8362536 Added custom player permission level 2017-08-10 11:34:34 +01:00
9bae4d8ef6 updates for 1.2.0.11 2017-08-10 11:15:23 +01:00
bb4808c23e attacking entities working
just moved some code :P
2017-08-10 10:49:14 +01:00
3025f76cd0 Fix a couple of Sign bugs 2017-08-10 08:57:57 +01:00
1e539c4e3b fix some 1.2 translation issues, close pmmp/PocketMine-Language#19 2017-08-09 21:40:20 +01:00
590003d7c1 Fixed PlayerListPacket 2017-08-09 19:51:39 +01:00
72d40860f3 Remove useless else branch and and return unhandled for unmatched window IDs 2017-08-09 19:05:00 +01:00
d3d1e32309 Removed teleport zero-offsets (not needed in 1.2) 2017-08-09 17:01:56 +01:00
36d47a33f3 Fixed crash on player death 2017-08-09 13:34:25 +01:00
260179197b Use SplFixedArrays in inventory, added more typehints and cleaned up some duplicated code 2017-08-09 13:12:07 +01:00
75644b5df2 s/windowid/windowId 2017-08-08 12:37:26 +01:00
3ad1b1ba7f Added some ContainerSetDataPacket constants 2017-08-08 12:19:11 +01:00
b4c2305c7f Minor cleanup of Human->initEntity() 2017-08-08 10:44:11 +01:00
1d0f0a2999 Merge branch 'master' into mcpe-1.2 2017-08-08 10:23:19 +01:00
8ca37b3813 Fixed a bug in multiline chat handling 2017-08-07 19:41:08 +01:00
2ba601b6e9 Fixed signs 2017-08-07 19:40:45 +01:00
7958fffa07 Move some code around to fix block placing, breaking, and throwing snowballs 2017-08-07 12:28:07 +01:00
98e0a2ecba Removed InventoryType, added new inventory API methods 2017-08-07 11:31:36 +01:00
899e318a88 Merge branch 'master' into mcpe-1.2 2017-08-06 18:46:56 +01:00
989505c42c Updated crafting & creative data from 1.2.0.7 2017-08-06 17:21:52 +01:00
d9da9accbc Fix packet buffers when encoding twice 2017-08-06 17:21:52 +01:00
711d62b5eb Updated block & item IDs from 1.2.0.7
Note to self: these may need updating again later in the beta.
2017-08-06 17:21:52 +01:00
49506659e0 More constants 2017-08-06 17:21:51 +01:00
7886918140 Cleaned up some bad code in DataPacket, added encode/decodeHeader and made encode/decodePayload protected 2017-08-06 17:21:51 +01:00
8a151dc373 Fixed PlayerSkinPacket for 1.2.0.7 2017-08-06 17:21:51 +01:00
58a12fdfa3 Updated for 1.2.0.7 2017-08-06 17:21:51 +01:00
50dffeb6a1 Day 3, part 1 2017-08-06 17:21:51 +01:00
63d2b341b9 Day 2 2017-08-06 17:21:51 +01:00
77cd8e7799 More broken mess to spawn 1.2 2017-08-06 17:21:51 +01:00
836 changed files with 46428 additions and 37370 deletions

View File

@ -3,16 +3,17 @@
THIS ISSUE TRACKER IS FOR BUG REPORTING, NOT FOR HELP & SUPPORT. If you need help, use the links below.
- http://pmmp.readthedocs.io/en/rtfd/ - Documentation
- https://forums.pmmp.io - PMMP Forums
-->
<!--- Any issues requesting updates to new versions of MCPE will be treated as spam. We do not need issues to tell us that there is a new version available. -->
<!---
Write a short description about the issue
If you are reporting a regression or unexpected behaviour, please include the below information:
Expected result: What were you expecting to happen?
Actual result: What actually happened?
Any issues requesting updates to new versions of MCPE will be treated as spam.
Please do not create issues for missing/un-implemented gameplay features - they will be closed.
-->
<!--- Write a short description about the issue -->
<!--- If you are reporting a regression or unexpected behaviour, please include the below information: -->
- Expected result: What were you expecting to happen?
- Actual result: What actually happened?
### Steps to reproduce the issue
<!--- help us find the problem by adding steps to reproduce the issue -->
1. ...
@ -21,9 +22,9 @@ Actual result: What actually happened?
### OS and versions
<!--- use the 'version' command in PocketMine-MP
NOTE: LATEST is not a valid version. PocketMine version should include Jenkins build number and/or git commit hash.
NOTE: LATEST is not a valid version. PocketMine-MP version should include Jenkins build number and/or git commit hash.
NO support whatsoever will be provided for forks or spoons of PocketMine. Issues relating to non-official distributions will be closed as spam. Please send such issues to whoever is responsible for the fork or spoon you are using.
NO support whatsoever will be provided for third-party modified variants of PocketMine-MP. Issues relating to third-party modifications will be closed as spam.
Note that 32-bit platforms are no longer supported by PocketMine-MP and issues concerning 32-bit platforms will be closed.
-->

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

12
.gitignore vendored
View File

@ -1,8 +1,9 @@
players/*
worlds/*
plugins/*
bin/*
bin*/*
timings/*
crashdumps/*
*.log
*.txt
*.phar
@ -28,3 +29,12 @@ Desktop.ini
# Sphinx-doc
/docs/build/
!/docs/requirements.txt
# Composer
vendor/*
# Travis files
test_data/*
# Doxygen
Documentation/*

7
.gitmodules vendored
View File

@ -1,10 +1,3 @@
[submodule "src/raklib"]
path = src/raklib
url = https://github.com/pmmp/RakLib.git
branch = master
[submodule "src/spl"]
path = src/spl
url = https://github.com/pmmp/PocketMine-SPL.git
[submodule "src/pocketmine/lang/locale"]
path = src/pocketmine/lang/locale
url = https://github.com/pmmp/PocketMine-Language.git

View File

@ -1,12 +1,21 @@
language: php
php:
- 7.0
- 7.2
before_script:
- pecl install channel://pecl.php.net/pthreads-3.1.6
- pecl install channel://pecl.php.net/weakref-0.3.3
- echo | pecl install channel://pecl.php.net/yaml-2.0.0
# - pecl install channel://pecl.php.net/pthreads-3.1.6
- echo | pecl install channel://pecl.php.net/yaml-2.0.2
- git clone https://github.com/krakjoe/pthreads.git
- cd pthreads
- git checkout d32079fb4a88e6e008104d36dbbf0c2dd7deb403
- phpize
- ./configure
- make
- make install
- cd ..
- echo "extension=pthreads.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- composer install
script:
- ./tests/travis.sh

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)__

52
composer.json Normal file
View File

@ -0,0 +1,52 @@
{
"name": "pocketmine/pocketmine-mp",
"description": "A server software for Minecraft: Pocket Edition written in PHP",
"type": "project",
"homepage": "https://pmmp.io",
"license": "LGPL-3.0",
"require": {
"php": ">=7.2.0RC3",
"ext-bcmath": "*",
"ext-curl": "*",
"ext-hash": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-pcre": "*",
"ext-phar": "*",
"ext-pthreads": ">=3.1.7dev",
"ext-reflection": "*",
"ext-sockets": "*",
"ext-spl": "*",
"ext-yaml": ">=2.0.0",
"ext-zip": "*",
"ext-zlib": ">=1.2.11",
"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": {
"": ["src"]
}
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/pmmp/RakLib"
},
{
"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"
}
]
}

178
composer.lock generated Normal file
View File

@ -0,0 +1,178 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"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": "5997f272811ed1148e7699a33335a0d2",
"packages": [
{
"name": "pocketmine/pocketmine-binaryutils",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/pmmp/PocketMine-BinaryUtils.git",
"reference": "a7cd5303a3b215d26bf9be76682ce9311f40e887"
},
"dist": {
"type": "zip",
"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",
"autoload": {
"exclude-from-classmap": [
"stubs"
],
"classmap": [
"./"
]
},
"license": [
"LGPL-3.0"
],
"description": "Standard library files required by PocketMine-MP and related projects",
"support": {
"source": "https://github.com/pmmp/PocketMine-SPL/tree/master"
},
"time": "2018-01-11T13:03:01+00:00"
},
{
"name": "pocketmine/raklib",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/pmmp/RakLib.git",
"reference": "eaa85c2b23bbc1a85030a621d4644c0e33e05950"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/eaa85c2b23bbc1a85030a621d4644c0e33e05950",
"reference": "eaa85c2b23bbc1a85030a621d4644c0e33e05950",
"shasum": ""
},
"require": {
"ext-bcmath": "*",
"ext-pthreads": ">=3.1.7dev",
"ext-sockets": "*",
"php": ">=7.2.0RC3",
"pocketmine/pocketmine-binaryutils": "dev-master#a7cd5303a3b215d26bf9be76682ce9311f40e887",
"pocketmine/pocketmine-spl": "^0.2.0"
},
"type": "library",
"autoload": {
"classmap": [
"./"
]
},
"license": [
"GPL-3.0"
],
"description": "A RakNet server implementation written in PHP",
"support": {
"source": "https://github.com/pmmp/RakLib/tree/master",
"issues": "https://github.com/pmmp/RakLib/issues"
},
"time": "2018-01-27T15:38:43+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"php": 5,
"ext-pthreads": 20,
"pocketmine/raklib": 20,
"pocketmine/pocketmine-binaryutils": 20,
"pocketmine/pocketmine-nbt": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=7.2.0RC3",
"ext-bcmath": "*",
"ext-curl": "*",
"ext-hash": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-pcre": "*",
"ext-phar": "*",
"ext-pthreads": ">=3.1.7dev",
"ext-reflection": "*",
"ext-sockets": "*",
"ext-spl": "*",
"ext-yaml": ">=2.0.0",
"ext-zip": "*",
"ext-zlib": ">=1.2.11"
},
"platform-dev": []
}

2322
doxygen.conf Normal file

File diff suppressed because it is too large Load Diff

View File

@ -116,7 +116,7 @@ abstract class Achievement{
public static function broadcast(Player $player, string $achievementId) : bool{
if(isset(Achievement::$list[$achievementId])){
$translation = new TranslationContainer("chat.type.achievement", [$player->getDisplayName(), TextFormat::GREEN . Achievement::$list[$achievementId]["name"] . TextFormat::RESET]);
if(Server::getInstance()->getConfigBoolean("announce-player-achievements", true) === true){
if(Server::getInstance()->getConfigBool("announce-player-achievements", true) === true){
Server::getInstance()->broadcastMessage($translation);
}else{
$player->sendMessage($translation);

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

@ -25,7 +25,9 @@ namespace pocketmine;
use pocketmine\event\server\LowMemoryEvent;
use pocketmine\event\Timings;
use pocketmine\scheduler\DumpWorkerMemoryTask;
use pocketmine\scheduler\GarbageCollectionTask;
use pocketmine\utils\MainLogger;
use pocketmine\utils\Utils;
class MemoryManager{
@ -63,16 +65,17 @@ class MemoryManager{
private $garbageCollectionAsync;
/** @var int */
private $chunkRadiusOverride;
private $lowMemChunkRadiusOverride;
/** @var bool */
private $chunkCollect;
/** @var bool */
private $chunkTrigger;
private $lowMemChunkGC;
/** @var bool */
private $chunkCache;
private $lowMemDisableChunkCache;
/** @var bool */
private $cacheTrigger;
private $lowMemClearWorldCache;
/** @var bool */
private $dumpWorkers = true;
public function __construct(Server $server){
$this->server = $server;
@ -124,13 +127,13 @@ class MemoryManager{
$this->garbageCollectionTrigger = (bool) $this->server->getProperty("memory.garbage-collection.low-memory-trigger", true);
$this->garbageCollectionAsync = (bool) $this->server->getProperty("memory.garbage-collection.collect-async-worker", true);
$this->chunkRadiusOverride = (int) $this->server->getProperty("memory.max-chunks.chunk-radius", 4);
$this->chunkCollect = (bool) $this->server->getProperty("memory.max-chunks.trigger-chunk-collect", true);
$this->chunkTrigger = (bool) $this->server->getProperty("memory.max-chunks.low-memory-trigger", true);
$this->lowMemChunkRadiusOverride = (int) $this->server->getProperty("memory.max-chunks.chunk-radius", 4);
$this->lowMemChunkGC = (bool) $this->server->getProperty("memory.max-chunks.trigger-chunk-collect", true);
$this->chunkCache = (bool) $this->server->getProperty("memory.world-caches.disable-chunk-cache", true);
$this->cacheTrigger = (bool) $this->server->getProperty("memory.world-caches.low-memory-trigger", true);
$this->lowMemDisableChunkCache = (bool) $this->server->getProperty("memory.world-caches.disable-chunk-cache", true);
$this->lowMemClearWorldCache = (bool) $this->server->getProperty("memory.world-caches.low-memory-trigger", true);
$this->dumpWorkers = (bool) $this->server->getProperty("memory.memory-dump.dump-async-worker", true);
gc_enable();
}
@ -145,7 +148,7 @@ class MemoryManager{
* @return bool
*/
public function canUseChunkCache() : bool{
return !($this->lowMemory and $this->chunkTrigger);
return !$this->lowMemory or !$this->lowMemDisableChunkCache;
}
/**
@ -156,7 +159,7 @@ class MemoryManager{
* @return int
*/
public function getViewDistance(int $distance) : int{
return $this->lowMemory ? (int) min($this->chunkRadiusOverride, $distance) : $distance;
return ($this->lowMemory and $this->lowMemChunkRadiusOverride > 0) ? (int) min($this->lowMemChunkRadiusOverride, $distance) : $distance;
}
/**
@ -170,13 +173,13 @@ class MemoryManager{
public function trigger(int $memory, int $limit, bool $global = false, int $triggerCount = 0){
$this->server->getLogger()->debug(sprintf("[Memory Manager] %sLow memory triggered, limit %gMB, using %gMB",
$global ? "Global " : "", round(($limit / 1024) / 1024, 2), round(($memory / 1024) / 1024, 2)));
if($this->cacheTrigger){
if($this->lowMemClearWorldCache){
foreach($this->server->getLevels() as $level){
$level->clearCache(true);
}
}
if($this->chunkTrigger and $this->chunkCollect){
if($this->lowMemChunkGC){
foreach($this->server->getLevels() as $level){
$level->doChunkGarbageCollection();
}
@ -261,6 +264,28 @@ class MemoryManager{
* @param int $maxStringSize
*/
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, $outputFolder, $maxNesting, $maxStringSize);
if($this->dumpWorkers){
$scheduler = $this->server->getScheduler();
for($i = 0, $size = $scheduler->getAsyncTaskPoolSize(); $i < $size; ++$i){
$scheduler->scheduleAsyncTaskToWorker(new DumpWorkerMemoryTask($outputFolder, $maxNesting, $maxStringSize), $i);
}
}
}
/**
* Static memory dumper accessible from any thread.
*
* @param mixed $startingObject
* @param string $outputFolder
* @param int $maxNesting
* @param int $maxStringSize
*
* @throws \ReflectionException
*/
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize){
$hardLimit = ini_get('memory_limit');
ini_set('memory_limit', '-1');
gc_disable();
@ -269,12 +294,8 @@ class MemoryManager{
mkdir($outputFolder, 0777, true);
}
$this->server->getLogger()->notice("[Dump] After the memory dump is done, the server might crash");
$obData = fopen($outputFolder . "/objects.js", "wb+");
$staticProperties = [];
$data = [];
$objects = [];
@ -283,8 +304,10 @@ class MemoryManager{
$instanceCounts = [];
$staticProperties = [];
$staticCount = 0;
foreach($this->server->getLoader()->getClasses() as $className){
foreach(get_declared_classes() as $className){
$reflection = new \ReflectionClass($className);
$staticProperties[$className] = [];
foreach($reflection->getProperties() as $property){
@ -297,7 +320,7 @@ class MemoryManager{
}
$staticCount++;
$this->continueDump($property->getValue(), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
self::continueDump($property->getValue(), $staticProperties[$className][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
if(count($staticProperties[$className]) === 0){
@ -305,9 +328,39 @@ class MemoryManager{
}
}
echo "[Dump] Wrote $staticCount static properties\n";
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
MainLogger::getLogger()->info("[Dump] Wrote $staticCount static properties");
$this->continueDump($this->server, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
if(isset($GLOBALS)){ //This might be null if we're on a different thread
$globalVariables = [];
$globalCount = 0;
$ignoredGlobals = [
'GLOBALS' => true,
'_SERVER' => true,
'_REQUEST' => true,
'_POST' => true,
'_GET' => true,
'_FILES' => true,
'_ENV' => true,
'_COOKIE' => true,
'_SESSION' => true
];
foreach($GLOBALS as $varName => $value){
if(isset($ignoredGlobals[$varName])){
continue;
}
$globalCount++;
self::continueDump($value, $globalVariables[$varName], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
file_put_contents($outputFolder . "/globalVariables.js", json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
MainLogger::getLogger()->info("[Dump] Wrote $globalCount global variables");
}
self::continueDump($startingObject, $data, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
do{
$continue = false;
@ -349,25 +402,26 @@ class MemoryManager{
if(!$property->isPublic()){
$property->setAccessible(true);
}
$this->continueDump($property->getValue($object), $info["properties"][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
self::continueDump($property->getValue($object), $info["properties"][$property->getName()], $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
fwrite($obData, "$hash@$className: " . json_encode($info, JSON_UNESCAPED_SLASHES) . "\n");
}
echo "[Dump] Wrote " . count($objects) . " objects\n";
}while($continue);
MainLogger::getLogger()->info("[Dump] Wrote " . count($objects) . " objects");
fclose($obData);
file_put_contents($outputFolder . "/staticProperties.js", json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents($outputFolder . "/serverEntry.js", json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents($outputFolder . "/referenceCounts.js", json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
arsort($instanceCounts, SORT_NUMERIC);
file_put_contents($outputFolder . "/instanceCounts.js", json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
echo "[Dump] Finished!\n";
MainLogger::getLogger()->info("[Dump] Finished!");
ini_set('memory_limit', $hardLimit);
gc_enable();
@ -382,7 +436,7 @@ class MemoryManager{
* @param int $maxNesting
* @param int $maxStringSize
*/
private function continueDump($from, &$data, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
private static function continueDump($from, &$data, array &$objects, array &$refCounts, int $recursion, int $maxNesting, int $maxStringSize){
if($maxNesting <= 0){
$data = "(error) NESTING LIMIT REACHED";
return;
@ -406,7 +460,7 @@ class MemoryManager{
}
$data = [];
foreach($from as $key => $value){
$this->continueDump($value, $data[$key], $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
self::continueDump($value, $data[$key], $objects, $refCounts, $recursion + 1, $maxNesting, $maxStringSize);
}
}elseif(is_string($from)){
$data = "(string) len(". strlen($from) .") " . substr(Utils::printable($from), 0, $maxStringSize);

View File

@ -108,11 +108,11 @@ class OfflinePlayer implements IPlayer, Metadatable{
}
public function getFirstPlayed(){
return $this->namedtag instanceof CompoundTag ? $this->namedtag["firstPlayed"] : null;
return $this->namedtag instanceof CompoundTag ? $this->namedtag->getLong("firstPlayed", 0, true) : null;
}
public function getLastPlayed(){
return $this->namedtag instanceof CompoundTag ? $this->namedtag["lastPlayed"] : null;
return $this->namedtag instanceof CompoundTag ? $this->namedtag->getLong("lastPlayed", 0, true) : null;
}
public function hasPlayedBefore() : bool{

File diff suppressed because it is too large Load Diff

View File

@ -70,6 +70,7 @@ namespace {
}
namespace pocketmine {
use pocketmine\utils\Binary;
use pocketmine\utils\MainLogger;
use pocketmine\utils\ServerKiller;
@ -78,9 +79,12 @@ namespace pocketmine {
use pocketmine\wizard\SetupWizard;
use raklib\RakLib;
const VERSION = "1.6.2dev";
const API_VERSION = "3.0.0-ALPHA7";
const CODENAME = "Unleashed";
const NAME = "PocketMine-MP";
const VERSION = "1.7dev";
const API_VERSION = "3.0.0-ALPHA11";
const CODENAME = "[REDACTED]";
const MIN_PHP_VERSION = "7.2.0RC3";
/*
* Startup code. Do not look at it, it may harm you.
@ -89,9 +93,9 @@ namespace pocketmine {
* Enjoy it as much as I did writing it. I don't want to do it again.
*/
if(version_compare("7.0", PHP_VERSION) > 0 or version_compare("7.1", PHP_VERSION) <= 0){
echo "[CRITICAL] You must use PHP 7.0" . PHP_EOL;
echo "[CRITICAL] Please use the installer provided on the homepage." . PHP_EOL;
if(version_compare(MIN_PHP_VERSION, PHP_VERSION) > 0){
echo "[CRITICAL] " . \pocketmine\NAME . " requires PHP >= " . MIN_PHP_VERSION . ", but you have PHP " . PHP_VERSION . "." . PHP_EOL;
echo "[CRITICAL] Please use the installer provided on the homepage, or update to a newer PHP version." . PHP_EOL;
exit(1);
}
@ -103,13 +107,15 @@ namespace pocketmine {
error_reporting(-1);
set_error_handler(function($severity, $message, $file, $line){
function error_handler($severity, $message, $file, $line){
if(error_reporting() & $severity){
throw new \ErrorException($message, 0, $severity, $file, $line);
}else{ //stfu operator
return true;
}
});
}
set_error_handler('\pocketmine\error_handler');
if(!extension_loaded("phar")){
echo "[CRITICAL] Unable to find the Phar extension." . PHP_EOL;
@ -120,42 +126,38 @@ namespace pocketmine {
if(\Phar::running(true) !== ""){
define('pocketmine\PATH', \Phar::running(true) . "/");
}else{
define('pocketmine\PATH', realpath(getcwd()) . DIRECTORY_SEPARATOR);
define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR);
}
$requiredSplVer = "0.0.1";
if(!is_file(\pocketmine\PATH . "src/spl/version.php") or version_compare($requiredSplVer, require(\pocketmine\PATH . "src/spl/version.php")) > 0){
echo "[CRITICAL] Incompatible PocketMine-SPL submodule version ($requiredSplVer is required)." . PHP_EOL;
echo "[CRITICAL] Please update your submodules or use provided builds." . PHP_EOL;
define('pocketmine\COMPOSER_AUTOLOADER_PATH', \pocketmine\PATH . 'vendor/autoload.php');
function composer_error_die($message){
echo "[CRITICAL] $message" . PHP_EOL;
echo "[CRITICAL] Please install/update Composer dependencies or use provided builds." . PHP_EOL;
exit(1);
}
if(!class_exists("ClassLoader", false)){
if(!is_file(\pocketmine\PATH . "src/spl/ClassLoader.php")){
echo "[CRITICAL] Unable to find the PocketMine-SPL library." . PHP_EOL;
echo "[CRITICAL] Please use provided builds or clone the repository recursively." . PHP_EOL;
exit(1);
}
require_once(\pocketmine\PATH . "src/spl/ClassLoader.php");
require_once(\pocketmine\PATH . "src/spl/BaseClassLoader.php");
if(is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){
require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH);
}else{
composer_error_die("Composer autoloader not found.");
}
$autoloader = new \BaseClassLoader();
$autoloader->addPath(\pocketmine\PATH . "src");
$autoloader->addPath(\pocketmine\PATH . "src" . DIRECTORY_SEPARATOR . "spl");
$autoloader->register(true);
if(!class_exists(RakLib::class)){
echo "[CRITICAL] Unable to find the RakLib library." . PHP_EOL;
echo "[CRITICAL] Please use provided builds or clone the repository recursively." . PHP_EOL;
exit(1);
composer_error_die("Unable to find the RakLib library.");
}
if(version_compare(RakLib::VERSION, "0.9.0") < 0){ //TODO: remove this check (it's managed by Composer now)
composer_error_die("RakLib version 0.9.0 is required, while you have version " . RakLib::VERSION . ".");
}
if(!class_exists(\BaseClassLoader::class)){
composer_error_die("Unable to find the PocketMine-SPL library.");
}
if(version_compare(RakLib::VERSION, "0.8.1") < 0){
echo "[CRITICAL] RakLib version 0.8.1 is required, while you have version " . RakLib::VERSION . "." . PHP_EOL;
echo "[CRITICAL] Please update your submodules or use provided builds." . PHP_EOL;
exit(1);
}
/*
* We now use the Composer autoloader, but this autoloader is still for loading plugins.
*/
$autoloader = new \BaseClassLoader();
$autoloader->register(false);
set_time_limit(0); //Who set it to 30 seconds?!?!
@ -167,10 +169,12 @@ namespace pocketmine {
ini_set("memory_limit", '-1');
define('pocketmine\START_TIME', microtime(true));
define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'src' . DIRECTORY_SEPARATOR . 'pocketmine' . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR);
$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();
@ -186,40 +190,51 @@ namespace pocketmine {
$logger = new MainLogger(\pocketmine\DATA . "server.log");
$logger->registerStatic();
if(!ini_get("date.timezone")){
do{
$timezone = ini_get("date.timezone");
if($timezone !== ""){
/*
* This is here so that people don't come to us complaining and fill up the issue tracker when they put
* an incorrect timezone abbreviation in php.ini apparently.
*/
if(strpos($timezone, "/") === false){
$default_timezone = timezone_name_from_abbr($timezone);
if($default_timezone !== false){
ini_set("date.timezone", $default_timezone);
date_default_timezone_set($default_timezone);
break;
}else{
//Bad php.ini value, try another method to detect timezone
$logger->warning("Timezone \"$timezone\" could not be parsed as a valid timezone from php.ini, falling back to auto-detection");
}
}else{
date_default_timezone_set($timezone);
break;
}
}
if(($timezone = detect_system_timezone()) and date_default_timezone_set($timezone)){
//Success! Timezone has already been set and validated in the if statement.
//This here is just for redundancy just in case some program wants to read timezone data from the ini.
ini_set("date.timezone", $timezone);
}else{
//If system timezone detection fails or timezone is an invalid value.
if($response = Utils::getURL("http://ip-api.com/json")
and $ip_geolocation_data = json_decode($response, true)
and $ip_geolocation_data['status'] !== 'fail'
and date_default_timezone_set($ip_geolocation_data['timezone'])
){
//Again, for redundancy.
ini_set("date.timezone", $ip_geolocation_data['timezone']);
}else{
ini_set("date.timezone", "UTC");
date_default_timezone_set("UTC");
$logger->warning("Timezone could not be automatically determined. An incorrect timezone will result in incorrect timestamps on console logs. It has been set to \"UTC\" by default. You can change it on the php.ini file.");
}
break;
}
}else{
/*
* This is here so that people don't come to us complaining and fill up the issue tracker when they put
* an incorrect timezone abbreviation in php.ini apparently.
*/
$timezone = ini_get("date.timezone");
if(strpos($timezone, "/") === false){
$default_timezone = timezone_name_from_abbr($timezone);
ini_set("date.timezone", $default_timezone);
date_default_timezone_set($default_timezone);
}else{
date_default_timezone_set($timezone);
if($response = Utils::getURL("http://ip-api.com/json") //If system timezone detection fails or timezone is an invalid value.
and $ip_geolocation_data = json_decode($response, true)
and $ip_geolocation_data['status'] !== 'fail'
and date_default_timezone_set($ip_geolocation_data['timezone'])
){
//Again, for redundancy.
ini_set("date.timezone", $ip_geolocation_data['timezone']);
break;
}
}
ini_set("date.timezone", "UTC");
date_default_timezone_set("UTC");
$logger->warning("Timezone could not be automatically determined or was set to an invalid value. An incorrect timezone will result in incorrect timestamps on console logs. It has been set to \"UTC\" by default. You can change it on the php.ini file.");
}while(false);
function detect_system_timezone(){
switch(Utils::getOS()){
@ -350,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");
@ -383,6 +402,12 @@ namespace pocketmine {
return -1;
}
/**
* @param int $start
* @param array|null $trace
*
* @return array
*/
function getTrace($start = 0, $trace = null){
if($trace === null){
if(function_exists("xdebug_get_function_stack")){
@ -408,7 +433,7 @@ namespace pocketmine {
return (is_object($value) ? get_class($value) . " object" : gettype($value) . " " . (is_array($value) ? "Array()" : Utils::printable(@strval($value))));
}, $args));
}
$messages[] = "#$j " . (isset($trace[$i]["file"]) ? cleanPath($trace[$i]["file"]) : "") . "(" . ($trace[$i]["line"] ?? "") . "): " . (isset($trace[$i]["class"]) ? $trace[$i]["class"] . (($trace[$i]["type"] === "dynamic" or $trace[$i]["type"] === "->") ? "->" : "::") : "") . $trace[$i]["function"] . "(" . Utils::printable($params) . ")";
$messages[] = "#$j " . (isset($trace[$i]["file"]) ? cleanPath($trace[$i]["file"]) : "") . "(" . (isset($trace[$i]["line"]) ? $trace[$i]["line"] : "") . "): " . (isset($trace[$i]["class"]) ? $trace[$i]["class"] . (($trace[$i]["type"] === "dynamic" or $trace[$i]["type"] === "->") ? "->" : "::") : "") . $trace[$i]["function"] . "(" . Utils::printable($params) . ")";
}
return $messages;
@ -424,13 +449,13 @@ namespace pocketmine {
$errors = 0;
if(PHP_INT_SIZE < 8){
$logger->critical("Running PocketMine-MP with 32-bit systems/PHP is no longer supported. Please upgrade to a 64-bit system or use a 64-bit PHP binary.");
$logger->critical("Running " . \pocketmine\NAME . " with 32-bit systems/PHP is no longer supported. Please upgrade to a 64-bit system or use a 64-bit PHP binary.");
$exitCode = 1;
break;
}
if(php_sapi_name() !== "cli"){
$logger->critical("You must run PocketMine-MP using the CLI.");
$logger->critical("You must run " . \pocketmine\NAME . " using the CLI.");
++$errors;
}
@ -438,15 +463,15 @@ namespace pocketmine {
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
if(version_compare($pthreads_version, "3.1.5") < 0){
$logger->critical("pthreads >= 3.1.5 is required, while you have $pthreads_version.");
if(version_compare($pthreads_version, "3.1.7-dev") < 0){
$logger->critical("pthreads >= 3.1.7-dev is required, while you have $pthreads_version.");
++$errors;
}
if(extension_loaded("leveldb")){
$leveldb_version = phpversion("leveldb");
if(version_compare($leveldb_version, "0.2.0") < 0){
$logger->critical("php-leveldb >= 0.2.0 is required, while you have $leveldb_version");
if(version_compare($leveldb_version, "0.2.1") < 0){
$logger->critical("php-leveldb >= 0.2.1 is required, while you have $leveldb_version");
++$errors;
}
}
@ -462,7 +487,7 @@ namespace pocketmine {
}
if(extension_loaded("xdebug")){
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running PocketMine with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
$logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running " . \pocketmine\NAME . " with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL);
}
$extensions = [
@ -470,8 +495,9 @@ namespace pocketmine {
"curl" => "cURL",
"json" => "JSON",
"mbstring" => "Multibyte String",
"yaml" => "YAML",
"openssl" => "OpenSSL",
"sockets" => "Sockets",
"yaml" => "YAML",
"zip" => "Zip",
"zlib" => "Zlib"
];
@ -509,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
@ -524,11 +549,11 @@ namespace pocketmine {
if(\Phar::running(true) === ""){
$logger->warning("Non-packaged PocketMine-MP installation detected, do not use on production.");
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
}
ThreadManager::init();
new Server($autoloader, $logger, \pocketmine\PATH, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);
$logger->info("Stopping other threads");
@ -536,19 +561,7 @@ namespace pocketmine {
$killer->start();
usleep(10000); //Fixes ServerKiller not being able to start on single-core machines
$erroredThreads = 0;
foreach(ThreadManager::getInstance()->getAll() as $id => $thread){
$logger->debug("Stopping " . $thread->getThreadName() . " thread");
try{
$thread->quit();
$logger->debug($thread->getThreadName() . " thread stopped successfully.");
}catch(\ThreadException $e){
++$erroredThreads;
$logger->debug("Could not stop " . $thread->getThreadName() . " thread: " . $e->getMessage());
}
}
if($erroredThreads > 0){
if(ThreadManager::getInstance()->stopAll() > 0){
if(\pocketmine\DEBUG > 1){
echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL;
}

View File

@ -36,6 +36,7 @@ use pocketmine\command\SimpleCommandMap;
use pocketmine\entity\Attribute;
use pocketmine\entity\Effect;
use pocketmine\entity\Entity;
use pocketmine\entity\Skin;
use pocketmine\event\HandlerList;
use pocketmine\event\level\LevelInitEvent;
use pocketmine\event\level\LevelLoadEvent;
@ -45,9 +46,7 @@ use pocketmine\event\server\ServerCommandEvent;
use pocketmine\event\TextContainer;
use pocketmine\event\Timings;
use pocketmine\event\TimingsHandler;
use pocketmine\event\TranslationContainer;
use pocketmine\inventory\CraftingManager;
use pocketmine\inventory\InventoryType;
use pocketmine\inventory\Recipe;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\ItemFactory;
@ -68,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;
@ -83,6 +83,7 @@ use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\PlayerListPacket;
use pocketmine\network\mcpe\protocol\ProtocolInfo;
use pocketmine\network\mcpe\protocol\types\PlayerListEntry;
use pocketmine\network\mcpe\RakLibInterface;
use pocketmine\network\Network;
use pocketmine\network\query\QueryHandler;
@ -114,8 +115,8 @@ use pocketmine\utils\VersionString;
* The class that manages everything
*/
class Server{
const BROADCAST_CHANNEL_ADMINISTRATIVE = "pocketmine.broadcast.admin";
const BROADCAST_CHANNEL_USERS = "pocketmine.broadcast.user";
public const BROADCAST_CHANNEL_ADMINISTRATIVE = "pocketmine.broadcast.admin";
public const BROADCAST_CHANNEL_USERS = "pocketmine.broadcast.user";
/** @var Server */
private static $instance = null;
@ -194,6 +195,9 @@ class Server{
/** @var int */
private $maxPlayers;
/** @var bool */
private $onlineMode = true;
/** @var bool */
private $autoSave;
@ -231,7 +235,6 @@ class Server{
private $serverID;
private $autoloader;
private $filePath;
private $dataPath;
private $pluginPath;
@ -273,7 +276,7 @@ class Server{
* @return string
*/
public function getName() : string{
return "PocketMine-MP";
return \pocketmine\NAME;
}
/**
@ -315,7 +318,14 @@ class Server{
* @return string
*/
public function getFilePath() : string{
return $this->filePath;
return \pocketmine\PATH;
}
/**
* @return string
*/
public function getResourcePath() : string{
return \pocketmine\RESOURCE_PATH;
}
/**
@ -339,6 +349,24 @@ class Server{
return $this->maxPlayers;
}
/**
* Returns whether the server requires that players be authenticated to Xbox Live. If true, connecting players who
* are not logged into Xbox Live will be disconnected.
*
* @return bool
*/
public function getOnlineMode() : bool{
return $this->onlineMode;
}
/**
* Alias of {@link #getOnlineMode()}.
* @return bool
*/
public function requiresAuthentication() : bool{
return $this->getOnlineMode();
}
/**
* @return int
*/
@ -406,7 +434,7 @@ class Server{
* @return bool
*/
public function getGenerateStructures() : bool{
return $this->getConfigBoolean("generate-structures", true);
return $this->getConfigBool("generate-structures", true);
}
/**
@ -420,7 +448,7 @@ class Server{
* @return bool
*/
public function getForceGamemode() : bool{
return $this->getConfigBoolean("force-gamemode", false);
return $this->getConfigBool("force-gamemode", false);
}
/**
@ -494,36 +522,17 @@ class Server{
}
/**
* @param string $str
* @deprecated Moved to {@link Level#getDifficultyFromString}
*
* @param string $str
* @return int
*/
public static function getDifficultyFromString(string $str) : int{
switch(strtolower(trim($str))){
case "0":
case "peaceful":
case "p":
return 0;
case "1":
case "easy":
case "e":
return 1;
case "2":
case "normal":
case "n":
return 2;
case "3":
case "hard":
case "h":
return 3;
}
return -1;
return Level::getDifficultyFromString($str);
}
/**
* Returns Server global difficulty. Note that this may be overridden in individual Levels.
* @return int
*/
public function getDifficulty() : int{
@ -534,7 +543,7 @@ class Server{
* @return bool
*/
public function hasWhitelist() : bool{
return $this->getConfigBoolean("white-list", false);
return $this->getConfigBool("white-list", false);
}
/**
@ -548,14 +557,14 @@ class Server{
* @return bool
*/
public function getAllowFlight() : bool{
return $this->getConfigBoolean("allow-flight", false);
return $this->getConfigBool("allow-flight", false);
}
/**
* @return bool
*/
public function isHardcore() : bool{
return $this->getConfigBoolean("hardcore", false);
return $this->getConfigBool("hardcore", false);
}
/**
@ -569,7 +578,7 @@ class Server{
* @return string
*/
public function getMotd() : string{
return $this->getConfigString("motd", "Minecraft: PE Server");
return $this->getConfigString("motd", \pocketmine\NAME . " Server");
}
/**
@ -741,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();
@ -754,32 +763,35 @@ class Server{
}
}
$spawn = $this->getDefaultLevel()->getSafeSpawn();
$currentTimeMillis = (int) (microtime(true) * 1000);
$nbt = new CompoundTag("", [
new LongTag("firstPlayed", (int) (microtime(true) * 1000)),
new LongTag("lastPlayed", (int) (microtime(true) * 1000)),
new LongTag("firstPlayed", $currentTimeMillis),
new LongTag("lastPlayed", $currentTimeMillis),
new ListTag("Pos", [
new DoubleTag("", $spawn->x),
new DoubleTag("", $spawn->y),
new DoubleTag("", $spawn->z)
]),
new StringTag("Level", $this->getDefaultLevel()->getName()),
//new StringTag("SpawnLevel", $this->getDefaultLevel()->getName()),
], NBT::TAG_Double),
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),
//new ByteTag("SpawnForced", 1), //TODO
new ListTag("Inventory", []),
new ListTag("Inventory", [], NBT::TAG_Compound),
new ListTag("EnderChestInventory", [], NBT::TAG_Compound),
new CompoundTag("Achievements", []),
new IntTag("playerGameType", $this->getGamemode()),
new ListTag("Motion", [
new DoubleTag("", 0.0),
new DoubleTag("", 0.0),
new DoubleTag("", 0.0)
]),
], NBT::TAG_Double),
new ListTag("Rotation", [
new FloatTag("", 0.0),
new FloatTag("", 0.0)
]),
], NBT::TAG_Float),
new FloatTag("FallDistance", 0.0),
new ShortTag("Fire", 0),
new ShortTag("Air", 300),
@ -787,10 +799,6 @@ class Server{
new ByteTag("Invulnerable", 0),
new StringTag("NameTag", $name)
]);
$nbt->Pos->setTagType(NBT::TAG_Double);
$nbt->Inventory->setTagType(NBT::TAG_Compound);
$nbt->Motion->setTagType(NBT::TAG_Double);
$nbt->Rotation->setTagType(NBT::TAG_Float);
return $nbt;
@ -808,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());
@ -915,7 +923,7 @@ class Server{
/**
* @return Level|null
*/
public function getDefaultLevel(){
public function getDefaultLevel() : ?Level{
return $this->levelDefault;
}
@ -926,7 +934,7 @@ class Server{
*
* @param Level|null $level
*/
public function setDefaultLevel($level){
public function setDefaultLevel(?Level $level) : void{
if($level === null or ($this->isLevelLoaded($level->getFolderName()) and $level !== $this->levelDefault)){
$this->levelDefault = $level;
}
@ -946,12 +954,8 @@ class Server{
*
* @return Level|null
*/
public function getLevel(int $levelId){
if(isset($this->levels[$levelId])){
return $this->levels[$levelId];
}
return null;
public function getLevel(int $levelId) : ?Level{
return $this->levels[$levelId] ?? null;
}
/**
@ -961,7 +965,7 @@ class Server{
*
* @return Level|null
*/
public function getLevelByName(string $name){
public function getLevelByName(string $name) : ?Level{
foreach($this->getLevels() as $level){
if($level->getFolderName() === $name){
return $level;
@ -983,13 +987,16 @@ class Server{
if($level === $this->getDefaultLevel() and !$forceUnload){
throw new \InvalidStateException("The default level cannot be unloaded while running, please switch levels.");
}
if($level->unload($forceUnload) === true){
unset($this->levels[$level->getId()]);
return true;
}
return $level->unload($forceUnload);
}
return false;
/**
* @internal
* @param Level $level
*/
public function removeLevel(Level $level) : void{
unset($this->levels[$level->getId()]);
}
/**
@ -1084,7 +1091,7 @@ class Server{
$level->setTickRate($this->baseTickRate);
}catch(\Throwable $e){
$this->logger->error($this->getLanguage()->translateString("pocketmine.level.generateError", [$name, $e->getMessage()]));
$this->logger->error($this->getLanguage()->translateString("pocketmine.level.generationError", [$name, $e->getMessage()]));
$this->logger->logException($e);
return false;
}
@ -1095,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 = [];
@ -1236,7 +1244,7 @@ class Server{
*
* @return bool
*/
public function getConfigBoolean(string $variable, bool $defaultValue = false) : bool{
public function getConfigBool(string $variable, bool $defaultValue = false) : bool{
$v = getopt("", ["$variable::"]);
if(isset($v[$variable])){
$value = $v[$variable];
@ -1258,6 +1266,18 @@ class Server{
return false;
}
/**
* @deprecated
*
* @param string $variable
* @param bool $defaultValue
*
* @return bool
*/
public function getConfigBoolean(string $variable, bool $defaultValue = false) : bool{
return $this->getConfigBool($variable, $defaultValue);
}
/**
* @param string $variable
* @param bool $value
@ -1381,7 +1401,7 @@ class Server{
if(is_array($value)){
$commands = $value;
}else{
$commands[] = $value;
$commands[] = (string) $value;
}
$result[$key] = $commands;
@ -1395,6 +1415,9 @@ class Server{
* @return Server
*/
public static function getInstance() : Server{
if(self::$instance === null){
throw new \RuntimeException("Attempt to retrieve Server instance outside server thread");
}
return self::$instance;
}
@ -1407,19 +1430,19 @@ class Server{
/**
* @param \ClassLoader $autoloader
* @param \ThreadedLogger $logger
* @param string $filePath
* @param string $dataPath
* @param string $pluginPath
*/
public function __construct(\ClassLoader $autoloader, \ThreadedLogger $logger, string $filePath, string $dataPath, 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;
$this->logger = $logger;
try{
$this->filePath = $filePath;
if(!file_exists($dataPath . "worlds/")){
mkdir($dataPath . "worlds/", 0777);
}
@ -1441,7 +1464,7 @@ class Server{
$this->logger->info("Loading pocketmine.yml...");
if(!file_exists($this->dataPath . "pocketmine.yml")){
$content = file_get_contents($this->filePath . "src/pocketmine/resources/pocketmine.yml");
$content = file_get_contents(\pocketmine\RESOURCE_PATH . "pocketmine.yml");
if($version->isDev()){
$content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content);
}
@ -1463,7 +1486,7 @@ class Server{
$this->logger->info("Loading server properties...");
$this->properties = new Config($this->dataPath . "server.properties", Config::PROPERTIES, [
"motd" => "Minecraft: PE Server",
"motd" => \pocketmine\NAME . " Server",
"server-port" => 19132,
"white-list" => false,
"announce-player-achievements" => true,
@ -1485,10 +1508,11 @@ class Server{
"enable-rcon" => false,
"rcon.password" => substr(base64_encode(random_bytes(20)), 3, 10),
"auto-save" => true,
"view-distance" => 8
"view-distance" => 8,
"xbox-auth" => true
]);
$this->forceLanguage = $this->getProperty("settings.force-language", false);
$this->forceLanguage = (bool) $this->getProperty("settings.force-language", false);
$this->baseLang = new BaseLang($this->getProperty("settings.language", BaseLang::FALLBACK_LANGUAGE));
$this->logger->info($this->getLanguage()->translateString("language.selected", [$this->getLanguage()->getName(), $this->getLanguage()->getLang()]));
@ -1503,6 +1527,8 @@ class Server{
if($processors > 0){
$poolSize = max(1, $processors);
}
}else{
$poolSize = (int) $poolSize;
}
ServerScheduler::$WORKERS = $poolSize;
@ -1512,7 +1538,12 @@ class Server{
}else{
Network::$BATCH_THRESHOLD = -1;
}
$this->networkCompressionLevel = $this->getProperty("network.compression-level", 7);
if($this->networkCompressionLevel < 1 or $this->networkCompressionLevel > 9){
$this->logger->warning("Invalid network compression level $this->networkCompressionLevel set, setting to default 7");
$this->networkCompressionLevel = 7;
}
$this->networkCompressionAsync = $this->getProperty("network.async-compression", true);
$this->autoTickRate = (bool) $this->getProperty("level-settings.auto-tick-rate", true);
@ -1524,7 +1555,7 @@ class Server{
$this->scheduler = new ServerScheduler();
if($this->getConfigBoolean("enable-rcon", false) === true){
if($this->getConfigBool("enable-rcon", false) === true){
try{
$this->rcon = new RCON(
$this,
@ -1556,10 +1587,20 @@ class Server{
$this->banByIP->load();
$this->maxPlayers = $this->getConfigInt("max-players", 20);
$this->setAutoSave($this->getConfigBoolean("auto-save", true));
$this->setAutoSave($this->getConfigBool("auto-save", true));
if($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3){
$this->setConfigInt("difficulty", 3);
$this->onlineMode = $this->getConfigBool("xbox-auth", true);
if($this->onlineMode){
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.auth", ["enabled", "will"]));
$this->logger->notice($this->getLanguage()->translateString("pocketmine.server.authProperty", ["disable", "false"]));
}else{
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.auth", ["disabled", "will not"]));
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.authWarning"));
$this->logger->warning($this->getLanguage()->translateString("pocketmine.server.authProperty", ["enable", "true"]));
}
if($this->getConfigBool("hardcore", false) === true and $this->getDifficulty() < Level::DIFFICULTY_HARD){
$this->setConfigInt("difficulty", Level::DIFFICULTY_HARD);
}
if(\pocketmine\DEBUG >= 0){
@ -1579,12 +1620,13 @@ class Server{
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.info", [
$this->getName(),
($version->isDev() ? TextFormat::YELLOW : "") . $version->get(true) . TextFormat::WHITE,
($version->isDev() ? TextFormat::YELLOW : "") . $version->get(true) . TextFormat::RESET,
$this->getCodename(),
$this->getApiVersion()
]));
$this->logger->info($this->getLanguage()->translateString("pocketmine.server.license", [$this->getName()]));
Timings::init();
$this->consoleSender = new ConsoleCommandSender();
@ -1592,7 +1634,6 @@ class Server{
Entity::init();
Tile::init();
InventoryType::init();
BlockFactory::init();
Enchantment::init();
ItemFactory::init();
@ -1601,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);
@ -1626,35 +1667,37 @@ class Server{
LevelProviderManager::addProvider(Anvil::class);
LevelProviderManager::addProvider(McRegion::class);
LevelProviderManager::addProvider(PMAnvil::class);
LevelProviderManager::addProvider(LevelDB::class);
if(extension_loaded("leveldb")){
$this->logger->debug($this->getLanguage()->translateString("pocketmine.debug.enable"));
LevelProviderManager::addProvider(LevelDB::class);
}
Generator::addGenerator(Flat::class, "flat");
Generator::addGenerator(Normal::class, "normal");
Generator::addGenerator(Normal::class, "default");
Generator::addGenerator(Nether::class, "hell");
Generator::addGenerator(Nether::class, "nether");
foreach((array) $this->getProperty("worlds", []) as $name => $worldSetting){
foreach((array) $this->getProperty("worlds", []) as $name => $options){
if(!is_array($options)){
continue;
}
if($this->loadLevel($name) === false){
$seed = $this->getProperty("worlds.$name.seed", time());
$seed = $options["seed"] ?? time();
if(is_string($seed) and !is_numeric($seed)){
$seed = Utils::javaStringHash($seed);
}elseif(!is_int($seed)){
$seed = (int) $seed;
}
$options = explode(":", $this->getProperty("worlds.$name.generator", Generator::getGenerator("default")));
$generator = Generator::getGenerator(array_shift($options));
if(count($options) > 0){
$options = [
"preset" => implode(":", $options)
];
if(isset($options["generator"])){
$generatorOptions = explode(":", $options["generator"]);
$generator = Generator::getGenerator(array_shift($generatorOptions));
if(count($options) > 0){
$options["preset"] = implode(":", $generatorOptions);
}
}else{
$options = [];
$generator = Generator::getGenerator("default");
}
$this->generateLevel($name, $seed, $generator, $options);
@ -1681,8 +1724,9 @@ class Server{
$this->setDefaultLevel($this->getLevelByName($default));
}
$this->properties->save(true);
if($this->properties->hasChanged()){
$this->properties->save(true);
}
if(!($this->getDefaultLevel() instanceof Level)){
$this->getLogger()->emergency($this->getLanguage()->translateString("pocketmine.level.defaultError"));
@ -1886,17 +1930,9 @@ class Server{
$pk->encode();
}
if($immediate){
foreach($identifiers as $i){
if(isset($this->players[$i])){
$this->players[$i]->directDataPacket($pk);
}
}
}else{
foreach($identifiers as $i){
if(isset($this->players[$i])){
$this->players[$i]->dataPacket($pk);
}
foreach($identifiers as $i){
if(isset($this->players[$i])){
$this->players[$i]->sendDataPacket($pk, false, $immediate);
}
}
@ -1955,7 +1991,7 @@ class Server{
}
$sender->sendMessage(new TranslationContainer(TextFormat::GOLD . "%commands.generic.notFound"));
$sender->sendMessage($this->getLanguage()->translateString(TextFormat::RED . "%commands.generic.notFound"));
return false;
}
@ -1975,8 +2011,8 @@ class Server{
$this->properties->reload();
$this->maxPlayers = $this->getConfigInt("max-players", 20);
if($this->getConfigBoolean("hardcore", false) === true and $this->getDifficulty() < 3){
$this->setConfigInt("difficulty", 3);
if($this->getConfigBool("hardcore", false) === true and $this->getDifficulty() < Level::DIFFICULTY_HARD){
$this->setConfigInt("difficulty", Level::DIFFICULTY_HARD);
}
$this->banByIP->load();
@ -2048,8 +2084,10 @@ class Server{
$this->scheduler->mainThreadHeartbeat(PHP_INT_MAX);
}
$this->getLogger()->debug("Saving properties");
$this->properties->save();
if($this->properties->hasChanged()){
$this->getLogger()->debug("Saving properties");
$this->properties->save();
}
$this->getLogger()->debug("Closing console");
$this->console->shutdown();
@ -2058,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);
@ -2082,8 +2122,8 @@ class Server{
/**
* Starts the PocketMine-MP server and starts processing ticks and packets
*/
public function start(){
if($this->getConfigBoolean("enable-query", true) === true){
private function start(){
if($this->getConfigBool("enable-query", true) === true){
$this->queryHandler = new QueryHandler();
}
@ -2125,6 +2165,10 @@ class Server{
}
}
/**
* @param \Throwable $e
* @param array|null $trace
*/
public function exceptionHandler(\Throwable $e, $trace = null){
if($e === null){
return;
@ -2271,7 +2315,7 @@ class Server{
}
public function addOnlinePlayer(Player $player){
$this->updatePlayerListData($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkinId(), $player->getSkinData());
$this->updatePlayerListData($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkin());
$this->playerList[$player->getRawUniqueId()] = $player;
}
@ -2280,32 +2324,44 @@ class Server{
if(isset($this->playerList[$player->getRawUniqueId()])){
unset($this->playerList[$player->getRawUniqueId()]);
$pk = new PlayerListPacket();
$pk->type = PlayerListPacket::TYPE_REMOVE;
$pk->entries[] = [$player->getUniqueId()];
$this->broadcastPacket($this->playerList, $pk);
$this->removePlayerListData($player->getUniqueId());
}
}
public function updatePlayerListData(UUID $uuid, $entityId, $name, $skinId, $skinData, array $players = null){
/**
* @param UUID $uuid
* @param int $entityId
* @param string $name
* @param Skin $skin
* @param Player[]|null $players
*/
public function updatePlayerListData(UUID $uuid, int $entityId, string $name, Skin $skin, array $players = null){
$pk = new PlayerListPacket();
$pk->type = PlayerListPacket::TYPE_ADD;
$pk->entries[] = [$uuid, $entityId, $name, $skinId, $skinData];
$pk->entries[] = PlayerListEntry::createAdditionEntry($uuid, $entityId, $name, $skin);
$this->broadcastPacket($players ?? $this->playerList, $pk);
}
/**
* @param UUID $uuid
* @param Player[]|null $players
*/
public function removePlayerListData(UUID $uuid, array $players = null){
$pk = new PlayerListPacket();
$pk->type = PlayerListPacket::TYPE_REMOVE;
$pk->entries[] = [$uuid];
$pk->entries[] = PlayerListEntry::createRemovalEntry($uuid);
$this->broadcastPacket($players ?? $this->playerList, $pk);
}
/**
* @param Player $p
*/
public function sendFullPlayerListData(Player $p){
$pk = new PlayerListPacket();
$pk->type = PlayerListPacket::TYPE_ADD;
foreach($this->playerList as $player){
$pk->entries[] = [$player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkinId(), $player->getSkinData()];
$pk->entries[] = PlayerListEntry::createAdditionEntry($player->getUniqueId(), $player->getId(), $player->getDisplayName(), $player->getSkin());
}
$p->dataPacket($pk);
@ -2315,7 +2371,7 @@ class Server{
foreach($this->players as $p){
if(!$p->loggedIn and ($tickTime - $p->creationTime) >= 10){
$p->close("", "Login timeout");
}elseif($this->alwaysTickPlayers and $p->joined){
}elseif($this->alwaysTickPlayers and $p->spawned){
$p->onUpdate($currentTick);
}
}
@ -2350,7 +2406,11 @@ class Server{
}
}
}catch(\Throwable $e){
$this->logger->critical($this->getLanguage()->translateString("pocketmine.level.tickError", [$level->getName(), $e->getMessage()]));
if(!$level->isClosed()){
$this->logger->critical($this->getLanguage()->translateString("pocketmine.level.tickError", [$level->getName(), $e->getMessage()]));
}else{
$this->logger->critical($this->getLanguage()->translateString("pocketmine.level.tickUnloadError", [$level->getName()]));
}
$this->logger->logException($e);
}
}
@ -2360,7 +2420,7 @@ class Server{
if($this->getAutoSave()){
Timings::$worldSaveTimer->startTiming();
foreach($this->players as $index => $player){
if($player->joined){
if($player->spawned){
$player->save(true);
}elseif(!$player->isConnected()){
$this->removePlayer($player);
@ -2375,7 +2435,7 @@ class Server{
}
public function sendUsage($type = SendUsageTask::TYPE_STATUS){
if($this->getProperty("anonymous-statistics.enabled", true)){
if((bool) $this->getProperty("anonymous-statistics.enabled", true)){
$this->scheduler->scheduleAsyncTask(new SendUsageTask($this, $type, $this->uniquePlayers));
}
$this->uniquePlayers = [];
@ -2426,8 +2486,6 @@ class Server{
" kB/s | TPS " . $this->getTicksPerSecondAverage() .
" | Load " . $this->getTickUsageAverage() . "%\x07";
$this->network->resetStatistics();
Timings::$titleTickTimer->stopTiming();
}
@ -2488,25 +2546,26 @@ class Server{
$player->checkNetwork();
}
if(($this->tickCounter & 0b1111) === 0){
if(($this->tickCounter % 20) === 0){
if($this->doTitleTick and Terminal::hasFormattingCodes()){
$this->titleTick();
}
$this->currentTPS = 20;
$this->currentUse = 0;
if(($this->tickCounter & 0b111111111) === 0){
try{
$this->getPluginManager()->callEvent($this->queryRegenerateTask = new QueryRegenerateEvent($this, 5));
if($this->queryHandler !== null){
$this->queryHandler->regenerateInfo();
}
}catch(\Throwable $e){
$this->logger->logException($e);
}
}
$this->network->updateName();
$this->network->resetStatistics();
}
$this->getNetwork()->updateName();
if(($this->tickCounter & 0b111111111) === 0){
try{
$this->getPluginManager()->callEvent($this->queryRegenerateTask = new QueryRegenerateEvent($this, 5));
if($this->queryHandler !== null){
$this->queryHandler->regenerateInfo();
}
}catch(\Throwable $e){
$this->logger->logException($e);
}
}
if($this->autoSave and ++$this->autoSaveTicker >= $this->autoSaveTicks){

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,16 +56,15 @@ abstract class Thread extends \Thread{
* (unless you are using a custom autoloader).
*/
public function registerClassLoader(){
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(true);
$this->classLoader->register(false);
}
}
public function start(int $options = PTHREADS_INHERIT_ALL){
public function start(?int $options = \PTHREADS_INHERIT_ALL){
ThreadManager::getInstance()->add($this);
if(!$this->isRunning() and !$this->isJoined() and !$this->isTerminated()){

View File

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine;
use pocketmine\utils\MainLogger;
class ThreadManager extends \Volatile{
/** @var ThreadManager */
@ -68,4 +70,23 @@ class ThreadManager extends \Volatile{
return $array;
}
}
public function stopAll() : int{
$logger = MainLogger::getLogger();
$erroredThreads = 0;
foreach($this->getAll() as $thread){
$logger->debug("Stopping " . $thread->getThreadName() . " thread");
try{
$thread->quit();
$logger->debug($thread->getThreadName() . " thread stopped successfully.");
}catch(\ThreadException $e){
++$erroredThreads;
$logger->debug("Could not stop " . $thread->getThreadName() . " thread: " . $e->getMessage());
}
}
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,16 +56,15 @@ abstract class Worker extends \Worker{
* (unless you are using a custom autoloader).
*/
public function registerClassLoader(){
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(true);
$this->classLoader->register(false);
}
}
public function start(int $options = PTHREADS_INHERIT_ALL){
public function start(?int $options = \PTHREADS_INHERIT_ALL){
ThreadManager::getInstance()->add($this);
if(!$this->isRunning() and !$this->isJoined() and !$this->isTerminated()){

View File

@ -24,6 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
/**
@ -32,7 +33,6 @@ use pocketmine\item\Item;
class Air extends Transparent{
protected $id = self::AIR;
protected $meta = 0;
public function __construct(int $meta = 0){
$this->meta = $meta;
@ -54,7 +54,7 @@ class Air extends Transparent{
return true;
}
public function canBeReplaced(Block $with = null) : bool{
public function canBeReplaced() : bool{
return true;
}
@ -66,10 +66,14 @@ class Air extends Transparent{
return false;
}
public function getBoundingBox(){
public function getBoundingBox() : ?AxisAlignedBB{
return null;
}
public function getCollisionBoxes() : array{
return [];
}
public function getHardness() : float{
return -1;
}
@ -78,4 +82,4 @@ class Air extends Transparent{
return 0;
}
}
}

View File

@ -26,26 +26,27 @@ 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;
class Anvil extends Fallable{
const TYPE_NORMAL = 0;
const TYPE_SLIGHTLY_DAMAGED = 4;
const TYPE_VERY_DAMAGED = 8;
public const TYPE_NORMAL = 0;
public const TYPE_SLIGHTLY_DAMAGED = 4;
public const TYPE_VERY_DAMAGED = 8;
protected $id = self::ANVIL;
public function isSolid() : bool{
return false;
}
public function __construct(int $meta = 0){
$this->meta = $meta;
}
public function isTransparent() : bool{
return true;
}
public function getHardness() : float{
return 5;
}
@ -64,7 +65,35 @@ 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{
$inset = 0.125;
if($this->meta & 0x01){ //east/west
return new AxisAlignedBB(
$this->x,
$this->y,
$this->z + $inset,
$this->x + 1,
$this->y + 1,
$this->z + 1 - $inset
);
}else{
return new AxisAlignedBB(
$this->x + $inset,
$this->y,
$this->z,
$this->x + 1 - $inset,
$this->y + 1,
$this->z + 1
);
}
}
public function onActivate(Item $item, Player $player = null) : bool{
@ -75,19 +104,15 @@ class Anvil extends Fallable{
return true;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$direction = ($player !== null ? $player->getDirection() : 0) & 0x03;
$this->meta = ($this->meta & 0x0c) | $direction;
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

@ -29,18 +29,14 @@ use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\Player;
use pocketmine\tile\Bed as TileBed;
use pocketmine\tile\Tile;
use pocketmine\utils\TextFormat;
class Bed extends Transparent{
const BITFLAG_OCCUPIED = 0x04;
const BITFLAG_HEAD = 0x08;
public const BITFLAG_OCCUPIED = 0x04;
public const BITFLAG_HEAD = 0x08;
protected $id = self::BED_BLOCK;
@ -58,7 +54,7 @@ class Bed extends Transparent{
return "Bed Block";
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return new AxisAlignedBB(
$this->x,
$this->y,
@ -129,7 +125,7 @@ class Bed extends Transparent{
/**
* @return Bed|null
*/
public function getOtherHalf(){
public function getOtherHalf() : ?Bed{
$other = $this->getSide(self::getOtherHalfSide($this->meta, $this->isHeadPart()));
if($other instanceof Bed and $other->getId() === $this->getId() and $other->isHeadPart() !== $this->isHeadPart() and (($other->getDamage() & 0x03) === ($this->getDamage() & 0x03))){
return $other;
@ -146,7 +142,7 @@ class Bed extends Transparent{
return true;
}elseif($player->distanceSquared($this) > 4 and $player->distanceSquared($other) > 4){
//MCPE doesn't have messages for bed too far away
$player->sendMessage(new TranslationContainer(TextFormat::GRAY . "%tile.bed.tooFar"));
return true;
}
@ -175,7 +171,7 @@ class Bed extends Transparent{
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if(!$down->isTransparent()){
$meta = (($player instanceof Player ? $player->getDirection() : 0) - 1) & 0x03;
@ -184,20 +180,8 @@ class Bed extends Transparent{
$this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->id, $meta), true, true);
$this->getLevel()->setBlock($next, BlockFactory::get($this->id, $meta | self::BITFLAG_HEAD), true, true);
$nbt = new CompoundTag("", [
new StringTag("id", Tile::BED),
new ByteTag("color", $item->getDamage() & 0x0f),
new IntTag("x", $blockReplace->x),
new IntTag("y", $blockReplace->y),
new IntTag("z", $blockReplace->z)
]);
$nbt2 = clone $nbt;
$nbt2["x"] = $next->x;
$nbt2["z"] = $next->z;
Tile::createTile(Tile::BED, $this->getLevel(), $nbt);
Tile::createTile(Tile::BED, $this->getLevel(), $nbt2);
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($this, $face, $item, $player));
Tile::createTile(Tile::BED, $this->getLevel(), TileBed::createNBT($next, $face, $item, $player));
return true;
}
@ -206,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, $player, $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
];
}
}
@ -232,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,16 +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;
@ -61,21 +61,25 @@ class Block extends Position implements BlockIds, Metadatable{
protected $id;
/** @var int */
protected $meta = 0;
/** @var string */
/** @var string|null */
protected $fallbackName;
/** @var int|null */
protected $itemId;
/** @var AxisAlignedBB */
public $boundingBox = null;
protected $boundingBox = null;
/** @var AxisAlignedBB[]|null */
protected $collisionBoxes = null;
/**
* @param int $id The block type's ID, 0-255
* @param int $meta Meta value of the block type
* @param string $name English name of the block type (TODO: implement translations)
* @param int $itemId The item ID of the block type, used for block picking and dropping items.
* @param int $id The block type's ID, 0-255
* @param int $meta Meta value of the block type
* @param string|null $name English name of the block type (TODO: implement translations)
* @param int $itemId The item ID of the block type, used for block picking and dropping items.
*/
public function __construct(int $id, int $meta = 0, string $name = "Unknown", int $itemId = null){
public function __construct(int $id, int $meta = 0, string $name = null, int $itemId = null){
$this->id = $id;
$this->meta = $meta;
$this->fallbackName = $name;
@ -86,7 +90,7 @@ class Block extends Position implements BlockIds, Metadatable{
* @return string
*/
public function getName() : string{
return $this->fallbackName;
return $this->fallbackName ?? "Unknown";
}
/**
@ -116,7 +120,7 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* @param int $meta
*/
final public function setDamage(int $meta){
final public function setDamage(int $meta) : void{
if($meta < 0 or $meta > 0xf){
throw new \InvalidArgumentException("Block damage values must be 0-15, not $meta");
}
@ -136,6 +140,34 @@ class Block extends Position implements BlockIds, Metadatable{
return -1;
}
/**
* Returns the block meta, stripped of non-variant flags.
* @return int
*/
public function getVariant() : int{
return $this->meta & $this->getVariantBitmask();
}
/**
* AKA: Block->isPlaceable
* @return bool
*/
public function canBePlaced() : bool{
return true;
}
/**
* @return bool
*/
public function canBeReplaced() : bool{
return false;
}
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
return $blockReplace->canBeReplaced();
}
/**
* Places the Block, using block space and block target, and side. Returns if the block has been placed.
*
@ -143,12 +175,12 @@ class Block extends Position implements BlockIds, Metadatable{
* @param Block $blockReplace
* @param Block $blockClicked
* @param int $face
* @param Vector3 $facePos
* @param Vector3 $clickVector
* @param Player|null $player
*
* @return bool
*/
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
return $this->getLevel()->setBlock($this, $this, true, true);
}
@ -163,6 +195,51 @@ class Block extends Position implements BlockIds, Metadatable{
return true;
}
/**
* @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);
}
/**
* Do the actions needed so the block is broken with the Item
*
@ -175,6 +252,42 @@ class Block extends Position implements BlockIds, Metadatable{
return $this->getLevel()->setBlock($this, BlockFactory::get(Block::AIR), true, true);
}
/**
* Returns the seconds that this block takes to be broken using an specific Item
*
* @param Item $item
*
* @return float
*/
public function getBreakTime(Item $item) : float{
$base = $this->getHardness();
if($this->isCompatibleWithTool($item)){
$base *= 1.5;
}else{
$base *= 5;
}
$efficiency = $item->getMiningEfficiency($this);
if($efficiency <= 0){
throw new \RuntimeException("Item efficiency is invalid");
}
$base /= $efficiency;
return $base;
}
/**
* Returns whether random block updates will be done on this block.
*
* @return bool
*/
public function ticksRandomly() : bool{
return false;
}
/**
* Fires a block update on the Block
*
@ -222,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
*/
@ -266,32 +372,6 @@ class Block extends Position implements BlockIds, Metadatable{
return false;
}
/**
* Returns whether random block updates will be done on this block.
*
* @return bool
*/
public function ticksRandomly() : bool{
return false;
}
/**
* AKA: Block->isPlaceable
* @return bool
*/
public function canBePlaced() : bool{
return true;
}
/**
* @param Block|null $with
*
* @return bool
*/
public function canBeReplaced(Block $with = null) : bool{
return false;
}
/**
* @return bool
*/
@ -328,7 +408,7 @@ class Block extends Position implements BlockIds, Metadatable{
}
public function addVelocityToEntity(Entity $entity, Vector3 $vector){
public function addVelocityToEntity(Entity $entity, Vector3 $vector) : void{
}
@ -337,7 +417,7 @@ class Block extends Position implements BlockIds, Metadatable{
*
* @param Position $v
*/
final public function position(Position $v){
final public function position(Position $v) : void{
$this->x = (int) $v->x;
$this->y = (int) $v->y;
$this->z = (int) $v->z;
@ -353,59 +433,59 @@ 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->getDamage() & $this->getVariantBitmask(), 1)
ItemFactory::get($this->getItemId(), $this->getVariant())
];
}
/**
* Returns the seconds that this block takes to be broken using an specific Item
* Returns an array of Items to be dropped when the block is broken using a compatible Silk Touch-enchanted tool.
*
* @param Item $item
*
* @return float
* @return Item[]
*/
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;
}
}
}else{
$base *= 3.33;
}
if($item->isSword()){
$base *= 0.5;
}
return $base;
public function getSilkTouchDrops(Item $item) : array{
return [
ItemFactory::get($this->getItemId(), $this->getVariant())
];
}
public function canBeBrokenWith(Item $item) : bool{
return $this->getHardness() !== -1;
/**
* 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
*/
public function getPickedItem() : Item{
return ItemFactory::get($this->getItemId(), $this->getVariant());
}
/**
@ -417,7 +497,7 @@ class Block extends Position implements BlockIds, Metadatable{
}
/**
* Returns the Block on the side $side, works like Vector3::side()
* Returns the Block on the side $side, works like Vector3::getSide()
*
* @param int $side
* @param int $step
@ -432,6 +512,45 @@ class Block extends Position implements BlockIds, Metadatable{
return BlockFactory::get(Block::AIR, 0, Position::fromObject(Vector3::getSide($side, $step)));
}
/**
* Returns the 4 blocks on the horizontal axes around the block (north, south, east, west)
*
* @return Block[]
*/
public function getHorizontalSides() : array{
return [
$this->getSide(Vector3::SIDE_NORTH),
$this->getSide(Vector3::SIDE_SOUTH),
$this->getSide(Vector3::SIDE_WEST),
$this->getSide(Vector3::SIDE_EAST)
];
}
/**
* Returns the six blocks around this block.
*
* @return Block[]
*/
public function getAllSides() : array{
return array_merge(
[
$this->getSide(Vector3::SIDE_DOWN),
$this->getSide(Vector3::SIDE_UP)
],
$this->getHorizontalSides()
);
}
/**
* 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
*/
@ -447,22 +566,50 @@ class Block extends Position implements BlockIds, Metadatable{
* @return bool
*/
public function collidesWithBB(AxisAlignedBB $bb) : bool{
$bb2 = $this->getBoundingBox();
$bbs = $this->getCollisionBoxes();
return $bb2 !== null and $bb->intersectsWith($bb2);
foreach($bbs as $bb2){
if($bb->intersectsWith($bb2)){
return true;
}
}
return false;
}
/**
* @param Entity $entity
*/
public function onEntityCollide(Entity $entity){
public function onEntityCollide(Entity $entity) : void{
}
/**
* @return AxisAlignedBB[]
*/
public function getCollisionBoxes() : array{
if($this->collisionBoxes === null){
$this->collisionBoxes = $this->recalculateCollisionBoxes();
}
return $this->collisionBoxes;
}
/**
* @return AxisAlignedBB[]
*/
protected function recalculateCollisionBoxes() : array{
if($bb = $this->recalculateBoundingBox()){
return [$bb];
}
return [];
}
/**
* @return AxisAlignedBB|null
*/
public function getBoundingBox(){
public function getBoundingBox() : ?AxisAlignedBB{
if($this->boundingBox === null){
$this->boundingBox = $this->recalculateBoundingBox();
}
@ -472,7 +619,7 @@ class Block extends Position implements BlockIds, Metadatable{
/**
* @return AxisAlignedBB|null
*/
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return new AxisAlignedBB(
$this->x,
$this->y,
@ -483,92 +630,46 @@ class Block extends Position implements BlockIds, Metadatable{
);
}
/**
* Clears any cached precomputed objects, such as bounding boxes. This is called on block neighbour update and when
* the block is set into the world to remove any outdated precomputed things such as AABBs and force recalculation.
*/
public function clearCaches() : void{
$this->boundingBox = null;
$this->collisionBoxes = null;
}
/**
* @param Vector3 $pos1
* @param Vector3 $pos2
*
* @return MovingObjectPosition|null
* @return RayTraceResult|null
*/
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2){
$bb = $this->getBoundingBox();
if($bb === null){
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{
$bbs = $this->getCollisionBoxes();
if(empty($bbs)){
return null;
}
$v1 = $pos1->getIntermediateWithXValue($pos2, $bb->minX);
$v2 = $pos1->getIntermediateWithXValue($pos2, $bb->maxX);
$v3 = $pos1->getIntermediateWithYValue($pos2, $bb->minY);
$v4 = $pos1->getIntermediateWithYValue($pos2, $bb->maxY);
$v5 = $pos1->getIntermediateWithZValue($pos2, $bb->minZ);
$v6 = $pos1->getIntermediateWithZValue($pos2, $bb->maxZ);
/** @var RayTraceResult|null $currentHit */
$currentHit = null;
/** @var int|float $currentDistance */
$currentDistance = PHP_INT_MAX;
if($v1 !== null and !$bb->isVectorInYZ($v1)){
$v1 = null;
foreach($bbs as $bb){
$nextHit = $bb->calculateIntercept($pos1, $pos2);
if($nextHit === null){
continue;
}
$nextDistance = $nextHit->hitVector->distanceSquared($pos1);
if($nextDistance < $currentDistance){
$currentHit = $nextHit;
$currentDistance = $nextDistance;
}
}
if($v2 !== null and !$bb->isVectorInYZ($v2)){
$v2 = null;
}
if($v3 !== null and !$bb->isVectorInXZ($v3)){
$v3 = null;
}
if($v4 !== null and !$bb->isVectorInXZ($v4)){
$v4 = null;
}
if($v5 !== null and !$bb->isVectorInXY($v5)){
$v5 = null;
}
if($v6 !== null and !$bb->isVectorInXY($v6)){
$v6 = null;
}
$vector = $v1;
if($v2 !== null and ($vector === null or $pos1->distanceSquared($v2) < $pos1->distanceSquared($vector))){
$vector = $v2;
}
if($v3 !== null and ($vector === null or $pos1->distanceSquared($v3) < $pos1->distanceSquared($vector))){
$vector = $v3;
}
if($v4 !== null and ($vector === null or $pos1->distanceSquared($v4) < $pos1->distanceSquared($vector))){
$vector = $v4;
}
if($v5 !== null and ($vector === null or $pos1->distanceSquared($v5) < $pos1->distanceSquared($vector))){
$vector = $v5;
}
if($v6 !== null and ($vector === null or $pos1->distanceSquared($v6) < $pos1->distanceSquared($vector))){
$vector = $v6;
}
if($vector === null){
return null;
}
$f = -1;
if($vector === $v1){
$f = 4;
}elseif($vector === $v2){
$f = 5;
}elseif($vector === $v3){
$f = 0;
}elseif($vector === $v4){
$f = 1;
}elseif($vector === $v5){
$f = 2;
}elseif($vector === $v6){
$f = 3;
}
return MovingObjectPosition::fromBlock($this->x, $this->y, $this->z, $f, $vector->add($this->x, $this->y, $this->z));
return $currentHit;
}
public function setMetadata(string $metadataKey, MetadataValue $newMetadataValue){

View File

@ -56,7 +56,7 @@ class BlockFactory{
*
* @param bool $force
*/
public static function init(bool $force = false){
public static function init(bool $force = false) : void{
if(self::$list === null or $force){
self::$list = new \SplFixedArray(256);
self::$fullList = new \SplFixedArray(4096);
@ -133,7 +133,7 @@ class BlockFactory{
self::registerBlock(new Furnace());
self::registerBlock(new BurningFurnace());
self::registerBlock(new SignPost());
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door Block", Item::OAK_DOOR));
self::registerBlock(new WoodenDoor(Block::OAK_DOOR_BLOCK, 0, "Oak Door", Item::OAK_DOOR));
self::registerBlock(new Ladder());
self::registerBlock(new Rail());
self::registerBlock(new CobblestoneStairs());
@ -153,8 +153,8 @@ class BlockFactory{
self::registerBlock(new Cactus());
self::registerBlock(new Clay());
self::registerBlock(new Sugarcane());
self::registerBlock(new Fence());
//TODO: JUKEBOX
self::registerBlock(new WoodenFence());
self::registerBlock(new Pumpkin());
self::registerBlock(new Netherrack());
self::registerBlock(new SoulSand());
@ -168,8 +168,8 @@ class BlockFactory{
self::registerBlock(new Trapdoor());
//TODO: MONSTER_EGG
self::registerBlock(new StoneBricks());
//TODO: BROWN_MUSHROOM_BLOCK
//TODO: RED_MUSHROOM_BLOCK
self::registerBlock(new BrownMushroomBlock());
self::registerBlock(new RedMushroomBlock());
self::registerBlock(new IronBars());
self::registerBlock(new GlassPane());
self::registerBlock(new Melon());
@ -199,7 +199,7 @@ class BlockFactory{
self::registerBlock(new CocoaBlock());
self::registerBlock(new SandstoneStairs());
self::registerBlock(new EmeraldOre());
//TODO: ENDER_CHEST
self::registerBlock(new EnderChest());
self::registerBlock(new TripwireHook());
self::registerBlock(new Tripwire());
self::registerBlock(new Emerald());
@ -245,12 +245,13 @@ class BlockFactory{
self::registerBlock(new Coal());
self::registerBlock(new PackedIce());
self::registerBlock(new DoublePlant());
self::registerBlock(new StandingBanner());
self::registerBlock(new WallBanner());
//TODO: DAYLIGHT_DETECTOR_INVERTED
//TODO: RED_SANDSTONE
//TODO: RED_SANDSTONE_STAIRS
//TODO: DOUBLE_STONE_SLAB2
//TODO: STONE_SLAB2
self::registerBlock(new RedSandstone());
self::registerBlock(new RedSandstoneStairs());
self::registerBlock(new DoubleStoneSlab2());
self::registerBlock(new StoneSlab2());
self::registerBlock(new FenceGate(Block::SPRUCE_FENCE_GATE, 0, "Spruce Fence Gate"));
self::registerBlock(new FenceGate(Block::BIRCH_FENCE_GATE, 0, "Birch Fence Gate"));
self::registerBlock(new FenceGate(Block::JUNGLE_FENCE_GATE, 0, "Jungle Fence Gate"));
@ -259,19 +260,20 @@ class BlockFactory{
//TODO: REPEATING_COMMAND_BLOCK
//TODO: CHAIN_COMMAND_BLOCK
self::registerBlock(new WoodenDoor(Block::SPRUCE_DOOR_BLOCK, 0, "Spruce Door Block", Item::SPRUCE_DOOR));
self::registerBlock(new WoodenDoor(Block::BIRCH_DOOR_BLOCK, 0, "Birch Door Block", Item::BIRCH_DOOR));
self::registerBlock(new WoodenDoor(Block::JUNGLE_DOOR_BLOCK, 0, "Jungle Door Block", Item::JUNGLE_DOOR));
self::registerBlock(new WoodenDoor(Block::ACACIA_DOOR_BLOCK, 0, "Acacia Door Block", Item::ACACIA_DOOR));
self::registerBlock(new WoodenDoor(Block::DARK_OAK_DOOR_BLOCK, 0, "Dark Oak Door Block", Item::DARK_OAK_DOOR));
self::registerBlock(new WoodenDoor(Block::SPRUCE_DOOR_BLOCK, 0, "Spruce Door", Item::SPRUCE_DOOR));
self::registerBlock(new WoodenDoor(Block::BIRCH_DOOR_BLOCK, 0, "Birch Door", Item::BIRCH_DOOR));
self::registerBlock(new WoodenDoor(Block::JUNGLE_DOOR_BLOCK, 0, "Jungle Door", Item::JUNGLE_DOOR));
self::registerBlock(new WoodenDoor(Block::ACACIA_DOOR_BLOCK, 0, "Acacia Door", Item::ACACIA_DOOR));
self::registerBlock(new WoodenDoor(Block::DARK_OAK_DOOR_BLOCK, 0, "Dark Oak Door", Item::DARK_OAK_DOOR));
self::registerBlock(new GrassPath());
self::registerBlock(new ItemFrame());
//TODO: CHORUS_FLOWER
//TODO: PURPUR_BLOCK
self::registerBlock(new Purpur());
//TODO: PURPUR_STAIRS
self::registerBlock(new PurpurStairs());
//TODO: END_BRICKS
//TODO: UNDYED_SHULKER_BOX
self::registerBlock(new EndStoneBricks());
//TODO: FROSTED_ICE
self::registerBlock(new EndRod());
//TODO: END_GATEWAY
@ -300,7 +302,7 @@ class BlockFactory{
self::registerBlock(new GlazedTerracotta(Block::RED_GLAZED_TERRACOTTA, 0, "Red Glazed Terracotta"));
self::registerBlock(new GlazedTerracotta(Block::BLACK_GLAZED_TERRACOTTA, 0, "Black Glazed Terracotta"));
self::registerBlock(new Concrete());
//TODO: CONCRETEPOWDER
self::registerBlock(new ConcretePowder());
//TODO: CHORUS_PLANT
self::registerBlock(new StainedGlass());
@ -314,6 +316,7 @@ class BlockFactory{
//TODO: INFO_UPDATE2
//TODO: MOVINGBLOCK
//TODO: OBSERVER
//TODO: STRUCTURE_BLOCK
//TODO: RESERVED6
@ -338,10 +341,10 @@ class BlockFactory{
* @throws \RuntimeException if something attempted to override an already-registered block without specifying the
* $override parameter.
*/
public static function registerBlock(Block $block, bool $override = false){
public static function registerBlock(Block $block, bool $override = false) : void{
$id = $block->getId();
if(self::$list[$id] !== null and !(self::$list[$id] instanceof UnknownBlock) and !$override){
if(!$override and self::isRegistered($id)){
throw new \RuntimeException("Trying to overwrite an already registered block");
}
@ -403,4 +406,15 @@ class BlockFactory{
public static function getBlockStatesArray() : \SplFixedArray{
return self::$fullList;
}
}
/**
* Returns whether a specified block ID is already registered in the block factory.
*
* @param int $id
* @return bool
*/
public static function isRegistered(int $id) : bool{
$b = self::$list[$id];
return $b !== null and !($b instanceof UnknownBlock);
}
}

View File

@ -25,252 +25,255 @@ namespace pocketmine\block;
interface BlockIds{
const AIR = 0;
const STONE = 1;
const GRASS = 2;
const DIRT = 3;
const COBBLESTONE = 4;
const PLANKS = 5, WOODEN_PLANKS = 5;
const SAPLING = 6;
const BEDROCK = 7;
const FLOWING_WATER = 8;
const STILL_WATER = 9, WATER = 9;
const FLOWING_LAVA = 10;
const LAVA = 11, STILL_LAVA = 11;
const SAND = 12;
const GRAVEL = 13;
const GOLD_ORE = 14;
const IRON_ORE = 15;
const COAL_ORE = 16;
const LOG = 17, WOOD = 17;
const LEAVES = 18;
const SPONGE = 19;
const GLASS = 20;
const LAPIS_ORE = 21;
const LAPIS_BLOCK = 22;
const DISPENSER = 23;
const SANDSTONE = 24;
const NOTEBLOCK = 25, NOTE_BLOCK = 25;
const BED_BLOCK = 26;
const GOLDEN_RAIL = 27, POWERED_RAIL = 27;
const DETECTOR_RAIL = 28;
const STICKY_PISTON = 29;
const COBWEB = 30, WEB = 30;
const TALLGRASS = 31, TALL_GRASS = 31;
const DEADBUSH = 32, DEAD_BUSH = 32;
const PISTON = 33;
const PISTONARMCOLLISION = 34, PISTON_ARM_COLLISION = 34;
const WOOL = 35;
public const AIR = 0;
public const STONE = 1;
public const GRASS = 2;
public const DIRT = 3;
public const COBBLESTONE = 4;
public const PLANKS = 5, WOODEN_PLANKS = 5;
public const SAPLING = 6;
public const BEDROCK = 7;
public const FLOWING_WATER = 8;
public const STILL_WATER = 9, WATER = 9;
public const FLOWING_LAVA = 10;
public const LAVA = 11, STILL_LAVA = 11;
public const SAND = 12;
public const GRAVEL = 13;
public const GOLD_ORE = 14;
public const IRON_ORE = 15;
public const COAL_ORE = 16;
public const LOG = 17, WOOD = 17;
public const LEAVES = 18;
public const SPONGE = 19;
public const GLASS = 20;
public const LAPIS_ORE = 21;
public const LAPIS_BLOCK = 22;
public const DISPENSER = 23;
public const SANDSTONE = 24;
public const NOTEBLOCK = 25, NOTE_BLOCK = 25;
public const BED_BLOCK = 26;
public const GOLDEN_RAIL = 27, POWERED_RAIL = 27;
public const DETECTOR_RAIL = 28;
public const STICKY_PISTON = 29;
public const COBWEB = 30, WEB = 30;
public const TALLGRASS = 31, TALL_GRASS = 31;
public const DEADBUSH = 32, DEAD_BUSH = 32;
public const PISTON = 33;
public const PISTONARMCOLLISION = 34, PISTON_ARM_COLLISION = 34;
public const WOOL = 35;
const DANDELION = 37, YELLOW_FLOWER = 37;
const POPPY = 38, RED_FLOWER = 38;
const BROWN_MUSHROOM = 39;
const RED_MUSHROOM = 40;
const GOLD_BLOCK = 41;
const IRON_BLOCK = 42;
const DOUBLE_STONE_SLAB = 43;
const STONE_SLAB = 44;
const BRICK_BLOCK = 45;
const TNT = 46;
const BOOKSHELF = 47;
const MOSSY_COBBLESTONE = 48, MOSS_STONE = 48;
const OBSIDIAN = 49;
const TORCH = 50;
const FIRE = 51;
const MOB_SPAWNER = 52, MONSTER_SPAWNER = 52;
const OAK_STAIRS = 53, WOODEN_STAIRS = 53;
const CHEST = 54;
const REDSTONE_WIRE = 55;
const DIAMOND_ORE = 56;
const DIAMOND_BLOCK = 57;
const CRAFTING_TABLE = 58, WORKBENCH = 58;
const WHEAT_BLOCK = 59;
const FARMLAND = 60;
const FURNACE = 61;
const BURNING_FURNACE = 62, LIT_FURNACE = 62;
const SIGN_POST = 63, STANDING_SIGN = 63;
const OAK_DOOR_BLOCK = 64, WOODEN_DOOR_BLOCK = 64;
const LADDER = 65;
const RAIL = 66;
const COBBLESTONE_STAIRS = 67, STONE_STAIRS = 67;
const WALL_SIGN = 68;
const LEVER = 69;
const STONE_PRESSURE_PLATE = 70;
const IRON_DOOR_BLOCK = 71;
const WOODEN_PRESSURE_PLATE = 72;
const REDSTONE_ORE = 73;
const GLOWING_REDSTONE_ORE = 74, LIT_REDSTONE_ORE = 74;
const UNLIT_REDSTONE_TORCH = 75;
const LIT_REDSTONE_TORCH = 76, REDSTONE_TORCH = 76;
const STONE_BUTTON = 77;
const SNOW_LAYER = 78;
const ICE = 79;
const SNOW = 80, SNOW_BLOCK = 80;
const CACTUS = 81;
const CLAY_BLOCK = 82;
const REEDS_BLOCK = 83, SUGARCANE_BLOCK = 83;
public const DANDELION = 37, YELLOW_FLOWER = 37;
public const POPPY = 38, RED_FLOWER = 38;
public const BROWN_MUSHROOM = 39;
public const RED_MUSHROOM = 40;
public const GOLD_BLOCK = 41;
public const IRON_BLOCK = 42;
public const DOUBLE_STONE_SLAB = 43;
public const STONE_SLAB = 44;
public const BRICK_BLOCK = 45;
public const TNT = 46;
public const BOOKSHELF = 47;
public const MOSSY_COBBLESTONE = 48, MOSS_STONE = 48;
public const OBSIDIAN = 49;
public const TORCH = 50;
public const FIRE = 51;
public const MOB_SPAWNER = 52, MONSTER_SPAWNER = 52;
public const OAK_STAIRS = 53, WOODEN_STAIRS = 53;
public const CHEST = 54;
public const REDSTONE_WIRE = 55;
public const DIAMOND_ORE = 56;
public const DIAMOND_BLOCK = 57;
public const CRAFTING_TABLE = 58, WORKBENCH = 58;
public const WHEAT_BLOCK = 59;
public const FARMLAND = 60;
public const FURNACE = 61;
public const BURNING_FURNACE = 62, LIT_FURNACE = 62;
public const SIGN_POST = 63, STANDING_SIGN = 63;
public const OAK_DOOR_BLOCK = 64, WOODEN_DOOR_BLOCK = 64;
public const LADDER = 65;
public const RAIL = 66;
public const COBBLESTONE_STAIRS = 67, STONE_STAIRS = 67;
public const WALL_SIGN = 68;
public const LEVER = 69;
public const STONE_PRESSURE_PLATE = 70;
public const IRON_DOOR_BLOCK = 71;
public const WOODEN_PRESSURE_PLATE = 72;
public const REDSTONE_ORE = 73;
public const GLOWING_REDSTONE_ORE = 74, LIT_REDSTONE_ORE = 74;
public const UNLIT_REDSTONE_TORCH = 75;
public const LIT_REDSTONE_TORCH = 76, REDSTONE_TORCH = 76;
public const STONE_BUTTON = 77;
public const SNOW_LAYER = 78;
public const ICE = 79;
public const SNOW = 80, SNOW_BLOCK = 80;
public const CACTUS = 81;
public const CLAY_BLOCK = 82;
public const REEDS_BLOCK = 83, SUGARCANE_BLOCK = 83;
public const JUKEBOX = 84;
public const FENCE = 85;
public const PUMPKIN = 86;
public const NETHERRACK = 87;
public const SOUL_SAND = 88;
public const GLOWSTONE = 89;
public const PORTAL = 90;
public const JACK_O_LANTERN = 91, LIT_PUMPKIN = 91;
public const CAKE_BLOCK = 92;
public const REPEATER_BLOCK = 93, UNPOWERED_REPEATER = 93;
public const POWERED_REPEATER = 94;
public const INVISIBLEBEDROCK = 95, INVISIBLE_BEDROCK = 95;
public const TRAPDOOR = 96, WOODEN_TRAPDOOR = 96;
public const MONSTER_EGG = 97;
public const STONEBRICK = 98, STONE_BRICK = 98, STONE_BRICKS = 98;
public const BROWN_MUSHROOM_BLOCK = 99;
public const RED_MUSHROOM_BLOCK = 100;
public const IRON_BARS = 101;
public const GLASS_PANE = 102;
public const MELON_BLOCK = 103;
public const PUMPKIN_STEM = 104;
public const MELON_STEM = 105;
public const VINE = 106, VINES = 106;
public const FENCE_GATE = 107, OAK_FENCE_GATE = 107;
public const BRICK_STAIRS = 108;
public const STONE_BRICK_STAIRS = 109;
public const MYCELIUM = 110;
public const LILY_PAD = 111, WATERLILY = 111, WATER_LILY = 111;
public const NETHER_BRICK_BLOCK = 112;
public const NETHER_BRICK_FENCE = 113;
public const NETHER_BRICK_STAIRS = 114;
public const NETHER_WART_PLANT = 115;
public const ENCHANTING_TABLE = 116, ENCHANTMENT_TABLE = 116;
public const BREWING_STAND_BLOCK = 117;
public const CAULDRON_BLOCK = 118;
public const END_PORTAL = 119;
public const END_PORTAL_FRAME = 120;
public const END_STONE = 121;
public const DRAGON_EGG = 122;
public const REDSTONE_LAMP = 123;
public const LIT_REDSTONE_LAMP = 124;
public const DROPPER = 125;
public const ACTIVATOR_RAIL = 126;
public const COCOA = 127, COCOA_BLOCK = 127;
public const SANDSTONE_STAIRS = 128;
public const EMERALD_ORE = 129;
public const ENDER_CHEST = 130;
public const TRIPWIRE_HOOK = 131;
public const TRIPWIRE = 132, TRIP_WIRE = 132;
public const EMERALD_BLOCK = 133;
public const SPRUCE_STAIRS = 134;
public const BIRCH_STAIRS = 135;
public const JUNGLE_STAIRS = 136;
public const COMMAND_BLOCK = 137;
public const BEACON = 138;
public const COBBLESTONE_WALL = 139, STONE_WALL = 139;
public const FLOWER_POT_BLOCK = 140;
public const CARROTS = 141, CARROT_BLOCK = 141;
public const POTATOES = 142, POTATO_BLOCK = 142;
public const WOODEN_BUTTON = 143;
public const MOB_HEAD_BLOCK = 144, SKULL_BLOCK = 144;
public const ANVIL = 145;
public const TRAPPED_CHEST = 146;
public const LIGHT_WEIGHTED_PRESSURE_PLATE = 147;
public const HEAVY_WEIGHTED_PRESSURE_PLATE = 148;
public const COMPARATOR_BLOCK = 149, UNPOWERED_COMPARATOR = 149;
public const POWERED_COMPARATOR = 150;
public const DAYLIGHT_DETECTOR = 151, DAYLIGHT_SENSOR = 151;
public const REDSTONE_BLOCK = 152;
public const NETHER_QUARTZ_ORE = 153, QUARTZ_ORE = 153;
public const HOPPER_BLOCK = 154;
public const QUARTZ_BLOCK = 155;
public const QUARTZ_STAIRS = 156;
public const DOUBLE_WOODEN_SLAB = 157;
public const WOODEN_SLAB = 158;
public const STAINED_CLAY = 159, STAINED_HARDENED_CLAY = 159, TERRACOTTA = 159;
public const STAINED_GLASS_PANE = 160;
public const LEAVES2 = 161;
public const LOG2 = 162, WOOD2 = 162;
public const ACACIA_STAIRS = 163;
public const DARK_OAK_STAIRS = 164;
public const SLIME = 165, SLIME_BLOCK = 165;
const FENCE = 85;
const PUMPKIN = 86;
const NETHERRACK = 87;
const SOUL_SAND = 88;
const GLOWSTONE = 89;
const PORTAL = 90;
const JACK_O_LANTERN = 91, LIT_PUMPKIN = 91;
const CAKE_BLOCK = 92;
const REPEATER_BLOCK = 93, UNPOWERED_REPEATER = 93;
const POWERED_REPEATER = 94;
const INVISIBLEBEDROCK = 95, INVISIBLE_BEDROCK = 95;
const TRAPDOOR = 96, WOODEN_TRAPDOOR = 96;
const MONSTER_EGG = 97;
const STONEBRICK = 98, STONE_BRICK = 98, STONE_BRICKS = 98;
const BROWN_MUSHROOM_BLOCK = 99;
const RED_MUSHROOM_BLOCK = 100;
const IRON_BARS = 101;
const GLASS_PANE = 102;
const MELON_BLOCK = 103;
const PUMPKIN_STEM = 104;
const MELON_STEM = 105;
const VINE = 106, VINES = 106;
const FENCE_GATE = 107, OAK_FENCE_GATE = 107;
const BRICK_STAIRS = 108;
const STONE_BRICK_STAIRS = 109;
const MYCELIUM = 110;
const LILY_PAD = 111, WATERLILY = 111, WATER_LILY = 111;
const NETHER_BRICK_BLOCK = 112;
const NETHER_BRICK_FENCE = 113;
const NETHER_BRICK_STAIRS = 114;
const NETHER_WART_PLANT = 115;
const ENCHANTING_TABLE = 116, ENCHANTMENT_TABLE = 116;
const BREWING_STAND_BLOCK = 117;
const CAULDRON_BLOCK = 118;
const END_PORTAL = 119;
const END_PORTAL_FRAME = 120;
const END_STONE = 121;
const DRAGON_EGG = 122;
const REDSTONE_LAMP = 123;
const LIT_REDSTONE_LAMP = 124;
const DROPPER = 125;
const ACTIVATOR_RAIL = 126;
const COCOA = 127, COCOA_BLOCK = 127;
const SANDSTONE_STAIRS = 128;
const EMERALD_ORE = 129;
const ENDER_CHEST = 130;
const TRIPWIRE_HOOK = 131;
const TRIPWIRE = 132, TRIP_WIRE = 132;
const EMERALD_BLOCK = 133;
const SPRUCE_STAIRS = 134;
const BIRCH_STAIRS = 135;
const JUNGLE_STAIRS = 136;
const COMMAND_BLOCK = 137;
const BEACON = 138;
const COBBLESTONE_WALL = 139, STONE_WALL = 139;
const FLOWER_POT_BLOCK = 140;
const CARROTS = 141, CARROT_BLOCK = 141;
const POTATOES = 142, POTATO_BLOCK = 142;
const WOODEN_BUTTON = 143;
const MOB_HEAD_BLOCK = 144, SKULL_BLOCK = 144;
const ANVIL = 145;
const TRAPPED_CHEST = 146;
const LIGHT_WEIGHTED_PRESSURE_PLATE = 147;
const HEAVY_WEIGHTED_PRESSURE_PLATE = 148;
const COMPARATOR_BLOCK = 149, UNPOWERED_COMPARATOR = 149;
const POWERED_COMPARATOR = 150;
const DAYLIGHT_DETECTOR = 151, DAYLIGHT_SENSOR = 151;
const REDSTONE_BLOCK = 152;
const NETHER_QUARTZ_ORE = 153, QUARTZ_ORE = 153;
const HOPPER_BLOCK = 154;
const QUARTZ_BLOCK = 155;
const QUARTZ_STAIRS = 156;
const DOUBLE_WOODEN_SLAB = 157;
const WOODEN_SLAB = 158;
const STAINED_CLAY = 159, STAINED_HARDENED_CLAY = 159, TERRACOTTA = 159;
const STAINED_GLASS_PANE = 160;
const LEAVES2 = 161;
const LOG2 = 162, WOOD2 = 162;
const ACACIA_STAIRS = 163;
const DARK_OAK_STAIRS = 164;
const SLIME = 165, SLIME_BLOCK = 165;
public const IRON_TRAPDOOR = 167;
public const PRISMARINE = 168;
public const SEALANTERN = 169, SEA_LANTERN = 169;
public const HAY_BALE = 170, HAY_BLOCK = 170;
public const CARPET = 171;
public const HARDENED_CLAY = 172;
public const COAL_BLOCK = 173;
public const PACKED_ICE = 174;
public const DOUBLE_PLANT = 175;
public const STANDING_BANNER = 176;
public const WALL_BANNER = 177;
public const DAYLIGHT_DETECTOR_INVERTED = 178, DAYLIGHT_SENSOR_INVERTED = 178;
public const RED_SANDSTONE = 179;
public const RED_SANDSTONE_STAIRS = 180;
public const DOUBLE_STONE_SLAB2 = 181;
public const STONE_SLAB2 = 182;
public const SPRUCE_FENCE_GATE = 183;
public const BIRCH_FENCE_GATE = 184;
public const JUNGLE_FENCE_GATE = 185;
public const DARK_OAK_FENCE_GATE = 186;
public const ACACIA_FENCE_GATE = 187;
public const REPEATING_COMMAND_BLOCK = 188;
public const CHAIN_COMMAND_BLOCK = 189;
const IRON_TRAPDOOR = 167;
const PRISMARINE = 168;
const SEALANTERN = 169, SEA_LANTERN = 169;
const HAY_BALE = 170, HAY_BLOCK = 170;
const CARPET = 171;
const HARDENED_CLAY = 172;
const COAL_BLOCK = 173;
const PACKED_ICE = 174;
const DOUBLE_PLANT = 175;
public const SPRUCE_DOOR_BLOCK = 193;
public const BIRCH_DOOR_BLOCK = 194;
public const JUNGLE_DOOR_BLOCK = 195;
public const ACACIA_DOOR_BLOCK = 196;
public const DARK_OAK_DOOR_BLOCK = 197;
public const GRASS_PATH = 198;
public const FRAME_BLOCK = 199, ITEM_FRAME_BLOCK = 199;
public const CHORUS_FLOWER = 200;
public const PURPUR_BLOCK = 201;
const DAYLIGHT_DETECTOR_INVERTED = 178, DAYLIGHT_SENSOR_INVERTED = 178;
const RED_SANDSTONE = 179;
const RED_SANDSTONE_STAIRS = 180;
const DOUBLE_STONE_SLAB2 = 181;
const STONE_SLAB2 = 182;
const SPRUCE_FENCE_GATE = 183;
const BIRCH_FENCE_GATE = 184;
const JUNGLE_FENCE_GATE = 185;
const DARK_OAK_FENCE_GATE = 186;
const ACACIA_FENCE_GATE = 187;
const REPEATING_COMMAND_BLOCK = 188;
const CHAIN_COMMAND_BLOCK = 189;
public const PURPUR_STAIRS = 203;
const SPRUCE_DOOR_BLOCK = 193;
const BIRCH_DOOR_BLOCK = 194;
const JUNGLE_DOOR_BLOCK = 195;
const ACACIA_DOOR_BLOCK = 196;
const DARK_OAK_DOOR_BLOCK = 197;
const GRASS_PATH = 198;
const FRAME_BLOCK = 199, ITEM_FRAME_BLOCK = 199;
const CHORUS_FLOWER = 200;
const PURPUR_BLOCK = 201;
public const UNDYED_SHULKER_BOX = 205;
public const END_BRICKS = 206;
public const FROSTED_ICE = 207;
public const END_ROD = 208;
public const END_GATEWAY = 209;
const PURPUR_STAIRS = 203;
public const MAGMA = 213;
public const NETHER_WART_BLOCK = 214;
public const RED_NETHER_BRICK = 215;
public const BONE_BLOCK = 216;
const END_BRICKS = 206;
const FROSTED_ICE = 207;
const END_ROD = 208;
const END_GATEWAY = 209;
public const SHULKER_BOX = 218;
public const PURPLE_GLAZED_TERRACOTTA = 219;
public const WHITE_GLAZED_TERRACOTTA = 220;
public const ORANGE_GLAZED_TERRACOTTA = 221;
public const MAGENTA_GLAZED_TERRACOTTA = 222;
public const LIGHT_BLUE_GLAZED_TERRACOTTA = 223;
public const YELLOW_GLAZED_TERRACOTTA = 224;
public const LIME_GLAZED_TERRACOTTA = 225;
public const PINK_GLAZED_TERRACOTTA = 226;
public const GRAY_GLAZED_TERRACOTTA = 227;
public const SILVER_GLAZED_TERRACOTTA = 228;
public const CYAN_GLAZED_TERRACOTTA = 229;
const MAGMA = 213;
const NETHER_WART_BLOCK = 214;
const RED_NETHER_BRICK = 215;
const BONE_BLOCK = 216;
public const BLUE_GLAZED_TERRACOTTA = 231;
public const BROWN_GLAZED_TERRACOTTA = 232;
public const GREEN_GLAZED_TERRACOTTA = 233;
public const RED_GLAZED_TERRACOTTA = 234;
public const BLACK_GLAZED_TERRACOTTA = 235;
public const CONCRETE = 236;
public const CONCRETEPOWDER = 237, CONCRETE_POWDER = 237;
const SHULKER_BOX = 218;
const PURPLE_GLAZED_TERRACOTTA = 219;
const WHITE_GLAZED_TERRACOTTA = 220;
const ORANGE_GLAZED_TERRACOTTA = 221;
const MAGENTA_GLAZED_TERRACOTTA = 222;
const LIGHT_BLUE_GLAZED_TERRACOTTA = 223;
const YELLOW_GLAZED_TERRACOTTA = 224;
const LIME_GLAZED_TERRACOTTA = 225;
const PINK_GLAZED_TERRACOTTA = 226;
const GRAY_GLAZED_TERRACOTTA = 227;
const SILVER_GLAZED_TERRACOTTA = 228;
const CYAN_GLAZED_TERRACOTTA = 229;
public const CHORUS_PLANT = 240;
public const STAINED_GLASS = 241;
const BLUE_GLAZED_TERRACOTTA = 231;
const BROWN_GLAZED_TERRACOTTA = 232;
const GREEN_GLAZED_TERRACOTTA = 233;
const RED_GLAZED_TERRACOTTA = 234;
const BLACK_GLAZED_TERRACOTTA = 235;
const CONCRETE = 236;
const CONCRETEPOWDER = 237, CONCRETE_POWDER = 237;
public const PODZOL = 243;
public const BEETROOT_BLOCK = 244;
public const STONECUTTER = 245;
public const GLOWINGOBSIDIAN = 246, GLOWING_OBSIDIAN = 246;
public const NETHERREACTOR = 247, NETHER_REACTOR = 247;
public const INFO_UPDATE = 248;
public const INFO_UPDATE2 = 249;
public const MOVINGBLOCK = 250, MOVING_BLOCK = 250;
public const OBSERVER = 251;
public const STRUCTURE_BLOCK = 252;
const CHORUS_PLANT = 240;
const STAINED_GLASS = 241;
const PODZOL = 243;
const BEETROOT_BLOCK = 244;
const STONECUTTER = 245;
const GLOWINGOBSIDIAN = 246, GLOWING_OBSIDIAN = 246;
const NETHERREACTOR = 247, NETHER_REACTOR = 247;
const INFO_UPDATE = 248;
const INFO_UPDATE2 = 249;
const MOVINGBLOCK = 250, MOVING_BLOCK = 250;
const OBSERVER = 251;
const RESERVED6 = 255;
public const RESERVED6 = 255;
}

View File

@ -21,21 +21,19 @@
declare(strict_types=1);
namespace pocketmine\inventory;
namespace pocketmine\block;
/**
* Saves all the information regarding default inventory sizes and types
* Types of tools that can be used to break blocks
* Blocks may allow multiple tool types by combining these bitflags
*/
interface SlotType{
const RESULT = 0;
interface BlockToolType{
const CRAFTING = 1; //Not used in Minecraft: PE yet
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;
const ARMOR = 2;
const CONTAINER = 3;
const HOTBAR = 4;
const FUEL = 5;
}
}

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,10 +46,14 @@ class BoneBlock extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
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{
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
return $this->getLevel()->setBlock($blockReplace, $this, true, true);
}
@ -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); // TODO: Change the autogenerated stub
}
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

@ -21,23 +21,21 @@
declare(strict_types=1);
namespace pocketmine\item;
namespace pocketmine\block;
use pocketmine\item\Item;
class WoodenSword extends Tool{
public function __construct(int $meta = 0){
parent::__construct(self::WOODEN_SWORD, $meta, "Wooden Sword");
class BrownMushroomBlock extends RedMushroomBlock{
protected $id = Block::BROWN_MUSHROOM_BLOCK;
public function getName() : string{
return "Brown Mushroom Block";
}
public function isSword(){
return Tool::TIER_WOODEN;
}
public function getFuelTime() : int{
return 200;
}
public function getAttackPoints() : int{
return 5;
public function getDropsForCompatibleTool(Item $item) : array{
return [
Item::get(Item::BROWN_MUSHROOM, 0, mt_rand(0, 2))
];
}
}

View File

@ -24,12 +24,8 @@ 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\NBT;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\Player;
use pocketmine\tile\Furnace as TileFurnace;
@ -39,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;
}
@ -52,14 +50,18 @@ 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{
return 13;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$faces = [
0 => 4,
1 => 2,
@ -68,26 +70,8 @@ class BurningFurnace extends Solid{
];
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
$this->getLevel()->setBlock($blockReplace, $this, true, true);
$nbt = new CompoundTag("", [
new ListTag("Items", []),
new StringTag("id", Tile::FURNACE),
new IntTag("x", $this->x),
new IntTag("y", $this->y),
new IntTag("z", $this->z)
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
if($item->hasCustomName()){
$nbt->CustomName = new StringTag("CustomName", $item->getCustomName());
}
if($item->hasCustomBlockData()){
foreach($item->getCustomBlockData() as $key => $v){
$nbt->{$key} = $v;
}
}
Tile::createTile("Furnace", $this->getLevel(), $nbt);
Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this, $face, $item, $player));
return true;
}
@ -96,21 +80,11 @@ class BurningFurnace extends Solid{
if($player instanceof Player){
$furnace = $this->getLevel()->getTile($this);
if(!($furnace instanceof TileFurnace)){
$nbt = new CompoundTag("", [
new ListTag("Items", []),
new StringTag("id", Tile::FURNACE),
new IntTag("x", $this->x),
new IntTag("y", $this->y),
new IntTag("z", $this->z)
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$furnace = Tile::createTile("Furnace", $this->getLevel(), $nbt);
$furnace = Tile::createTile(Tile::FURNACE, $this->getLevel(), TileFurnace::createNBT($this));
}
if(isset($furnace->namedtag->Lock) and $furnace->namedtag->Lock instanceof StringTag){
if($furnace->namedtag->Lock->getValue() !== $item->getCustomName()){
return true;
}
if($furnace->namedtag->hasTag("Lock", StringTag::class) and $furnace->namedtag->getString("Lock") !== $item->getCustomName()){
return true;
}
$player->addWindow($furnace->getInventory());
@ -122,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

@ -0,0 +1,51 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\Player;
abstract class Button extends Flowable{
public function __construct(int $meta = 0){
$this->meta = $meta;
}
public function getVariantBitmask() : int{
return 0;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
//TODO: check valid target block
$this->meta = $face;
return $this->level->setBlock($this, $this, true, true);
}
public function onActivate(Item $item, Player $player = null) : bool{
//TODO
return true;
}
}

View File

@ -54,7 +54,7 @@ class Cactus extends Transparent{
return "Cactus";
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return new AxisAlignedBB(
$this->x + 0.0625,
@ -70,7 +70,7 @@ class Cactus extends Transparent{
return true;
}
public function onEntityCollide(Entity $entity){
public function onEntityCollide(Entity $entity) : void{
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_CONTACT, 1);
$entity->attack($ev);
}
@ -92,7 +92,7 @@ class Cactus extends Transparent{
if($this->getSide(Vector3::SIDE_DOWN)->getId() !== self::CACTUS){
if($this->meta === 0x0f){
for($y = 1; $y < 3; ++$y){
$b = $this->getLevel()->getBlock(new Vector3($this->x, $this->y + $y, $this->z));
$b = $this->getLevel()->getBlockAt($this->x, $this->y + $y, $this->z);
if($b->getId() === self::AIR){
Server::getInstance()->getPluginManager()->callEvent($ev = new BlockGrowEvent($b, BlockFactory::get(Block::CACTUS)));
if(!$ev->isCancelled()){
@ -112,7 +112,7 @@ class Cactus extends Transparent{
return false;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::SAND or $down->getId() === self::CACTUS){
$block0 = $this->getSide(Vector3::SIDE_NORTH);
@ -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,10 +45,10 @@ class Cake extends Transparent implements FoodSource{
}
public function getName() : string{
return "Cake Block";
return "Cake";
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
$f = $this->getDamage() * 0.125; //1 slice width
@ -62,7 +62,7 @@ class Cake extends Transparent implements FoodSource{
);
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() !== self::AIR){
$this->getLevel()->setBlock($blockReplace, $this, true, true);
@ -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

@ -50,7 +50,7 @@ class Carpet extends Flowable{
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Carpet";
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return new AxisAlignedBB(
$this->x,
@ -62,7 +62,7 @@ class Carpet extends Flowable{
);
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() !== self::AIR){
$this->getLevel()->setBlock($blockReplace, $this, true, true);
@ -85,4 +85,4 @@ class Carpet extends Flowable{
return false;
}
}
}

View File

@ -38,9 +38,13 @@ 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)
];
}
}
public function getPickedItem() : Item{
return ItemFactory::get(Item::CARROT);
}
}

View File

@ -24,13 +24,8 @@ 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\NBT;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\Player;
use pocketmine\tile\Chest as TileChest;
@ -53,21 +48,22 @@ class Chest extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_AXE;
return BlockToolType::TYPE_AXE;
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
//these are slightly bigger than in PC
return new AxisAlignedBB(
$this->x + 0.0625,
$this->x + 0.025,
$this->y,
$this->z + 0.0625,
$this->x + 0.9375,
$this->y + 0.9475,
$this->z + 0.9375
$this->z + 0.025,
$this->x + 0.975,
$this->y + 0.95,
$this->z + 0.975
);
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$faces = [
0 => 4,
1 => 2,
@ -95,26 +91,7 @@ class Chest extends Transparent{
}
$this->getLevel()->setBlock($blockReplace, $this, true, true);
$nbt = new CompoundTag("", [
new ListTag("Items", []),
new StringTag("id", Tile::CHEST),
new IntTag("x", $this->x),
new IntTag("y", $this->y),
new IntTag("z", $this->z)
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
if($item->hasCustomName()){
$nbt->CustomName = new StringTag("CustomName", $item->getCustomName());
}
if($item->hasCustomBlockData()){
foreach($item->getCustomBlockData() as $key => $v){
$nbt->{$key} = $v;
}
}
$tile = Tile::createTile("Chest", $this->getLevel(), $nbt);
$tile = Tile::createTile(Tile::CHEST, $this->getLevel(), TileChest::createNBT($this, $face, $item, $player));
if($chest instanceof TileChest and $tile instanceof TileChest){
$chest->pairWith($tile);
@ -124,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){
@ -142,21 +109,13 @@ class Chest extends Transparent{
if($t instanceof TileChest){
$chest = $t;
}else{
$nbt = new CompoundTag("", [
new ListTag("Items", []),
new StringTag("id", Tile::CHEST),
new IntTag("x", $this->x),
new IntTag("y", $this->y),
new IntTag("z", $this->z)
]);
$nbt->Items->setTagType(NBT::TAG_Compound);
$chest = Tile::createTile("Chest", $this->getLevel(), $nbt);
$chest = Tile::createTile(Tile::CHEST, $this->getLevel(), TileChest::createNBT($this));
}
if(
!$this->getSide(Vector3::SIDE_UP)->isTransparent() or
($chest->isPaired() and !$chest->getPair()->getBlock()->getSide(Vector3::SIDE_UP)->isTransparent()) or
(isset($chest->namedtag->Lock) and $chest->namedtag->Lock instanceof StringTag and $chest->namedtag->Lock->getValue() !== $item->getCustomName())
($chest->namedtag->hasTag("Lock", StringTag::class) and $chest->namedtag->getString("Lock") !== $item->getCustomName())
){
return true;
}
@ -174,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,13 +23,13 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
class CobblestoneWall extends Transparent{
const NONE_MOSSY_WALL = 0;
const MOSSY_WALL = 1;
public const NONE_MOSSY_WALL = 0;
public const MOSSY_WALL = 1;
protected $id = self::COBBLESTONE_WALL;
@ -37,12 +37,12 @@ class CobblestoneWall extends Transparent{
$this->meta = $meta;
}
public function isSolid() : bool{
return false;
public function getToolType() : int{
return BlockToolType::TYPE_PICKAXE;
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getHardness() : float{
@ -57,38 +57,38 @@ class CobblestoneWall extends Transparent{
return "Cobblestone Wall";
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
//walls don't have any special collision boxes like fences do
$north = $this->canConnect($this->getSide(Vector3::SIDE_NORTH));
$south = $this->canConnect($this->getSide(Vector3::SIDE_SOUTH));
$west = $this->canConnect($this->getSide(Vector3::SIDE_WEST));
$east = $this->canConnect($this->getSide(Vector3::SIDE_EAST));
$n = $north ? 0 : 0.25;
$s = $south ? 1 : 0.75;
$w = $west ? 0 : 0.25;
$e = $east ? 1 : 0.75;
if($north and $south and !$west and !$east){
$w = 0.3125;
$e = 0.6875;
}elseif(!$north and !$south and $west and $east){
$n = 0.3125;
$s = 0.6875;
$inset = 0.25;
if(
$this->getSide(Vector3::SIDE_UP)->getId() === Block::AIR and //if there is a block on top, it stays as a post
(
($north and $south and !$west and !$east) or
(!$north and !$south and $west and $east)
)
){
//If connected to two sides on the same axis but not any others, AND there is not a block on top, there is no post and the wall is thinner
$inset = 0.3125;
}
return new AxisAlignedBB(
$this->x + $w,
$this->x + ($west ? 0 : $inset),
$this->y,
$this->z + $n,
$this->x + $e,
$this->z + ($north ? 0 : $inset),
$this->x + 1 - ($east ? 0 : $inset),
$this->y + 1.5,
$this->z + $s
$this->z + 1 - ($south ? 0 : $inset)
);
}
public function canConnect(Block $block){
return ($block->getId() !== self::COBBLESTONE_WALL and $block->getId() !== self::FENCE_GATE) ? $block->isSolid() and !$block->isTransparent() : true;
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
}
}

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 onEntityCollide(Entity $entity){
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

@ -23,7 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
class CocoaBlock extends Solid{
class CocoaBlock extends Transparent{
protected $id = self::COCOA_BLOCK;
@ -35,5 +35,17 @@ class CocoaBlock extends Solid{
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

@ -0,0 +1,77 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\ColorBlockMetaHelper;
use pocketmine\level\Level;
class ConcretePowder extends Fallable{
protected $id = self::CONCRETE_POWDER;
public function __construct(int $meta = 0){
$this->meta = $meta;
}
public function getName() : string{
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Concrete Powder";
}
public function getHardness() : float{
return 0.5;
}
public function getToolType() : int{
return BlockToolType::TYPE_SHOVEL;
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL and ($block = $this->checkAdjacentWater()) !== null){
$this->level->setBlock($this, $block);
return $type;
}
return parent::onUpdate($type);
}
/**
* @return null|Block
*/
public function tickFalling() : ?Block{
return $this->checkAdjacentWater();
}
/**
* @return null|Block
*/
private function checkAdjacentWater() : ?Block{
for($i = 1; $i < 6; ++$i){ //Do not check underneath
if($this->getSide($i) instanceof Water){
return Block::get(Block::CONCRETE, $this->meta);
}
}
return null;
}
}

View File

@ -23,8 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\inventory\BigCraftingGrid;
use pocketmine\item\Item;
use pocketmine\item\Tool;
use pocketmine\Player;
class CraftingTable extends Solid{
@ -44,12 +44,12 @@ 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{
if($player instanceof Player){
$player->craftingType = 1;
$player->setCraftingGrid(new BigCraftingGrid($player));
}
return true;
@ -58,4 +58,4 @@ class CraftingTable extends Solid{
public function getFuelTime() : int{
return 300;
}
}
}

View File

@ -32,7 +32,7 @@ use pocketmine\Server;
abstract class Crops extends Flowable{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if($blockReplace->getSide(Vector3::SIDE_DOWN)->getId() === Block::FARMLAND){
$this->getLevel()->setBlock($blockReplace, $this, true, true);
@ -95,4 +95,8 @@ abstract class Crops extends Flowable{
return false;
}
}
public function isAffectedBySilkTouch() : bool{
return false;
}
}

View File

@ -41,7 +41,7 @@ class Dandelion extends Flowable{
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
$this->getLevel()->setBlock($blockReplace, $this, true, true);
@ -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

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
@ -38,7 +40,6 @@ class DeadBush extends Flowable{
return "Dead Bush";
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent() === true){
@ -51,4 +52,21 @@ class DeadBush extends Flowable{
return false;
}
}
public function getToolType() : int{
return BlockToolType::TYPE_SHEARS;
}
public function getToolHarvestLevel() : int{
return 1;
}
public function getDrops(Item $item) : array{
if(!$this->isCompatibleWithTool($item)){
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,21 +39,28 @@ class Dirt extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_SHOVEL;
return BlockToolType::TYPE_SHOVEL;
}
public function getName() : string{
if($this->meta === 1){
return "Coarse Dirt";
}
return "Dirt";
}
public function onActivate(Item $item, Player $player = null) : bool{
if($item->isHoe()){
$item->useOn($this);
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND, 0), true);
if($this->meta === 1){
$this->getLevel()->setBlock($this, BlockFactory::get(Block::DIRT), true);
}else{
$this->getLevel()->setBlock($this, BlockFactory::get(Block::FARMLAND), true);
}
return true;
}
return false;
}
}
}

View File

@ -54,7 +54,7 @@ abstract class Door extends Transparent{
return $down & 0x07 | ($isUp ? 8 : 0) | ($isRight ? 0x10 : 0);
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
$f = 0.1875;
$damage = $this->getFullDamage();
@ -216,7 +216,7 @@ abstract class Door extends Transparent{
return false;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if($face === Vector3::SIDE_UP){
$blockUp = $this->getSide(Vector3::SIDE_UP);
$blockDown = $this->getSide(Vector3::SIDE_DOWN);
@ -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

@ -30,7 +30,7 @@ use pocketmine\math\Vector3;
use pocketmine\Player;
class DoublePlant extends Flowable{
const BITFLAG_TOP = 0x08;
public const BITFLAG_TOP = 0x08;
protected $id = self::DOUBLE_PLANT;
@ -38,7 +38,7 @@ class DoublePlant extends Flowable{
$this->meta = $meta;
}
public function canBeReplaced(Block $with = null) : bool{
public function canBeReplaced() : bool{
return $this->meta === 2 or $this->meta === 3; //grass or fern
}
@ -51,10 +51,10 @@ class DoublePlant extends Flowable{
4 => "Rose Bush",
5 => "Peony"
];
return $names[$this->meta & 0x07] ?? "";
return $names[$this->getVariant()] ?? "";
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$id = $blockReplace->getSide(Vector3::SIDE_DOWN)->getId();
if(($id === Block::GRASS or $id === Block::DIRT) and $blockReplace->getSide(Vector3::SIDE_UP)->canBeReplaced()){
$this->getLevel()->setBlock($blockReplace, $this, false, false);
@ -79,7 +79,7 @@ class DoublePlant extends Flowable{
return (
$other->getId() === $this->getId() and
($other->getDamage() & 0x07) === ($this->getDamage() & 0x07) and
$other->getVariant() === $this->getVariant() and
($other->getDamage() & self::BITFLAG_TOP) !== ($this->getDamage() & self::BITFLAG_TOP)
);
}
@ -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

@ -0,0 +1,50 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
abstract class DoubleSlab extends Solid{
public function __construct(int $meta = 0){
$this->meta = $meta;
}
abstract public function getSlabId() : int;
public function getName() : string{
return "Double " . BlockFactory::get($this->getSlabId(), $this->getVariant())->getName() . " Slab";
}
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get($this->getSlabId(), $this->getVariant(), 2)
];
}
public function isAffectedBySilkTouch() : bool{
return false;
}
}

View File

@ -23,16 +23,14 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
use pocketmine\item\TieredTool;
class DoubleStoneSlab extends Solid{
class DoubleStoneSlab extends DoubleSlab{
protected $id = self::DOUBLE_STONE_SLAB;
public function __construct(int $meta = 0){
$this->meta = $meta;
public function getSlabId() : int{
return self::STONE_SLAB;
}
public function getHardness() : float{
@ -40,31 +38,10 @@ class DoubleStoneSlab extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function getName() : string{
static $names = [
0 => "Stone",
1 => "Sandstone",
2 => "Wooden",
3 => "Cobblestone",
4 => "Brick",
5 => "Stone Brick",
6 => "Quartz",
7 => "Nether Brick"
];
return "Double " . $names[$this->meta & 0x07] . " Slab";
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getDrops(Item $item) : array{
if($item->isPickaxe() >= Tool::TIER_WOODEN){
return [
ItemFactory::get(Item::STONE_SLAB, $this->getDamage() & 0x07, 2)
];
}
return [];
}
}
}

View File

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

View File

@ -23,16 +23,12 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\Tool;
class DoubleWoodenSlab extends Solid{
class DoubleWoodenSlab extends DoubleSlab{
protected $id = self::DOUBLE_WOODEN_SLAB;
public function __construct(int $meta = 0){
$this->meta = $meta;
public function getSlabId() : int{
return self::WOODEN_SLAB;
}
public function getHardness() : float{
@ -40,25 +36,6 @@ class DoubleWoodenSlab extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_AXE;
return BlockToolType::TYPE_AXE;
}
public function getName() : string{
static $names = [
0 => "Oak",
1 => "Spruce",
2 => "Birch",
3 => "Jungle",
4 => "Acacia",
5 => "Dark Oak"
];
return "Double " . ($names[$this->meta & 0x07] ?? "") . " Wooden Slab";
}
public function getDrops(Item $item) : array{
return [
ItemFactory::get(Item::WOODEN_SLAB, $this->getDamage() & 0x07, 2)
];
}
}
}

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,12 +25,10 @@ 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\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\Player;
use pocketmine\tile\EnchantTable as TileEnchantTable;
use pocketmine\tile\Tile;
class EnchantingTable extends Transparent{
@ -41,26 +39,10 @@ class EnchantingTable extends Transparent{
$this->meta = $meta;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$this->getLevel()->setBlock($blockReplace, $this, true, true);
$nbt = new CompoundTag("", [
new StringTag("id", Tile::ENCHANT_TABLE),
new IntTag("x", $this->x),
new IntTag("y", $this->y),
new IntTag("z", $this->z)
]);
if($item->hasCustomName()){
$nbt->CustomName = new StringTag("CustomName", $item->getCustomName());
}
if($item->hasCustomBlockData()){
foreach($item->getCustomBlockData() as $key => $v){
$nbt->{$key} = $v;
}
}
Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel(), $nbt);
Tile::createTile(Tile::ENCHANT_TABLE, $this->getLevel(), TileEnchantTable::createNBT($this, $face, $item, $player));
return true;
}
@ -78,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{
@ -90,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

@ -54,7 +54,7 @@ class EndPortalFrame extends Solid{
return false;
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return new AxisAlignedBB(
$this->x,
@ -65,4 +65,4 @@ class EndPortalFrame extends Solid{
$this->z + 1
);
}
}
}

View File

@ -40,7 +40,7 @@ class EndRod extends Flowable{
return "End Rod";
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if($face === Vector3::SIDE_UP or $face === Vector3::SIDE_DOWN){
$this->meta = $face;
}else{
@ -61,7 +61,7 @@ class EndRod extends Flowable{
return 14;
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
$m = $this->meta & ~0x01;
$width = 0.375;
@ -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

@ -0,0 +1,51 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\TieredTool;
class EndStoneBricks extends Solid{
protected $id = self::END_BRICKS;
public function __construct(int $meta = 0){
$this->meta = $meta;
}
public function getName() : string{
return "End Stone Bricks";
}
public function getHardness() : float{
return 0.8;
}
public function getToolType() : int{
return BlockToolType::TYPE_PICKAXE;
}
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
}

View File

@ -0,0 +1,110 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\TieredTool;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\tile\EnderChest as TileEnderChest;
use pocketmine\tile\Tile;
class EnderChest extends Chest{
protected $id = self::ENDER_CHEST;
public function getHardness() : float{
return 22.5;
}
public function getBlastResistance() : float{
return 3000;
}
public function getLightLevel() : int{
return 7;
}
public function getName() : string{
return "Ender Chest";
}
public function getToolType() : int{
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{
$faces = [
0 => 4,
1 => 2,
2 => 5,
3 => 3
];
$this->meta = $faces[$player instanceof Player ? $player->getDirection() : 0];
$this->getLevel()->setBlock($blockReplace, $this, true, true);
Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this, $face, $item, $player));
return true;
}
public function onActivate(Item $item, Player $player = null) : bool{
if($player instanceof Player){
$t = $this->getLevel()->getTile($this);
$enderChest = null;
if($t instanceof TileEnderChest){
$enderChest = $t;
}else{
$enderChest = Tile::createTile(Tile::ENDER_CHEST, $this->getLevel(), TileEnderChest::createNBT($this));
}
if(!$this->getSide(Vector3::SIDE_UP)->isTransparent()){
return true;
}
$player->getEnderChestInventory()->setHolderPosition($enderChest);
$player->addWindow($player->getEnderChestInventory());
}
return true;
}
public function getDropsForCompatibleTool(Item $item) : array{
return [
ItemFactory::get(Item::OBSIDIAN, 0, 8)
];
}
public function getFuelTime() : int{
return 0;
}
}

View File

@ -26,41 +26,32 @@ namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\level\Level;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\ByteTag;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
abstract class Fallable extends Solid{
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL){
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === self::AIR or ($down instanceof Liquid)){
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true, true);
$fall = Entity::createEntity("FallingSand", $this->getLevel(), new CompoundTag("", [
new ListTag("Pos", [
new DoubleTag("", $this->x + 0.5),
new DoubleTag("", $this->y),
new DoubleTag("", $this->z + 0.5)
]),
new ListTag("Motion", [
new DoubleTag("", 0),
new DoubleTag("", 0),
new DoubleTag("", 0)
]),
new ListTag("Rotation", [
new FloatTag("", 0),
new FloatTag("", 0)
]),
new IntTag("TileID", $this->getId()),
new ByteTag("Data", $this->getDamage())
]));
if($down->getId() === self::AIR or $down instanceof Liquid or $down instanceof Fire){
$this->level->setBlock($this, BlockFactory::get(Block::AIR), true);
$fall->spawnToAll();
$nbt = Entity::createBaseNBT($this->add(0.5, 0, 0.5));
$nbt->setInt("TileID", $this->getId());
$nbt->setByte("Data", $this->getDamage());
$fall = Entity::createEntity("FallingSand", $this->getLevel(), $nbt);
if($fall !== null){
$fall->spawnToAll();
}
}
}
}
}
/**
* @return null|Block
*/
public function tickFalling() : ?Block{
return null;
}
}

View File

@ -25,9 +25,9 @@ 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;
class Farmland extends Transparent{
@ -46,14 +46,14 @@ class Farmland extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_SHOVEL;
return BlockToolType::TYPE_SHOVEL;
}
public function ticksRandomly() : bool{
return true;
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return new AxisAlignedBB(
$this->x,
$this->y,
@ -65,16 +65,55 @@ class Farmland extends Transparent{
}
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_RANDOM){
//TODO: hydration
if($type === Level::BLOCK_UPDATE_NORMAL and $this->getSide(Vector3::SIDE_UP)->isSolid()){
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
return $type;
}elseif($type === Level::BLOCK_UPDATE_RANDOM){
if(!$this->canHydrate()){
if($this->meta > 0){
$this->meta--;
$this->level->setBlock($this, $this, false, false);
}else{
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), false, true);
}
return $type;
}elseif($this->meta < 7){
$this->meta = 7;
$this->level->setBlock($this, $this, false, false);
return $type;
}
}
return false;
}
public function getDrops(Item $item) : array{
protected function canHydrate() : bool{
//TODO: check rain
$start = $this->add(-4, 0, -4);
$end = $this->add(4, 1, 4);
for($y = $start->y; $y <= $end->y; ++$y){
for($z = $start->z; $z <= $end->z; ++$z){
for($x = $start->x; $x <= $end->x; ++$x){
$id = $this->level->getBlockIdAt($x, $y, $z);
if($id === Block::STILL_WATER or $id === Block::FLOWING_WATER){
return true;
}
}
}
}
return false;
}
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

@ -23,73 +23,87 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Tool;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
class Fence extends Transparent{
const FENCE_OAK = 0;
const FENCE_SPRUCE = 1;
const FENCE_BIRCH = 2;
const FENCE_JUNGLE = 3;
const FENCE_ACACIA = 4;
const FENCE_DARKOAK = 5;
protected $id = self::FENCE;
abstract class Fence extends Transparent{
public function __construct(int $meta = 0){
$this->meta = $meta;
}
public function getHardness() : float{
return 2;
public function getThickness() : float{
return 0.25;
}
public function getToolType() : int{
return Tool::TYPE_AXE;
}
public function getName() : string{
static $names = [
self::FENCE_OAK => "Oak Fence",
self::FENCE_SPRUCE => "Spruce Fence",
self::FENCE_BIRCH => "Birch Fence",
self::FENCE_JUNGLE => "Jungle Fence",
self::FENCE_ACACIA => "Acacia Fence",
self::FENCE_DARKOAK => "Dark Oak Fence"
];
return $names[$this->meta & 0x07] ?? "Unknown";
}
protected function recalculateBoundingBox(){
$north = $this->canConnect($this->getSide(Vector3::SIDE_NORTH));
$south = $this->canConnect($this->getSide(Vector3::SIDE_SOUTH));
$west = $this->canConnect($this->getSide(Vector3::SIDE_WEST));
$east = $this->canConnect($this->getSide(Vector3::SIDE_EAST));
$n = $north ? 0 : 0.375;
$s = $south ? 1 : 0.625;
$w = $west ? 0 : 0.375;
$e = $east ? 1 : 0.625;
protected function recalculateBoundingBox() : ?AxisAlignedBB{
$width = 0.5 - $this->getThickness() / 2;
return new AxisAlignedBB(
$this->x + $w,
$this->x + ($this->canConnect($this->getSide(Vector3::SIDE_WEST)) ? 0 : $width),
$this->y,
$this->z + $n,
$this->x + $e,
$this->z + ($this->canConnect($this->getSide(Vector3::SIDE_NORTH)) ? 0 : $width),
$this->x + 1 - ($this->canConnect($this->getSide(Vector3::SIDE_EAST)) ? 0 : $width),
$this->y + 1.5,
$this->z + $s
$this->z + 1 - ($this->canConnect($this->getSide(Vector3::SIDE_SOUTH)) ? 0 : $width)
);
}
public function canConnect(Block $block){
return ($block instanceof Fence or $block instanceof FenceGate) ? true : $block->isSolid() and !$block->isTransparent();
protected function recalculateCollisionBoxes() : array{
$inset = 0.5 - $this->getThickness() / 2;
/** @var AxisAlignedBB[] $bbs */
$bbs = [];
$connectWest = $this->canConnect($this->getSide(Vector3::SIDE_WEST));
$connectEast = $this->canConnect($this->getSide(Vector3::SIDE_EAST));
if($connectWest or $connectEast){
//X axis (west/east)
$bbs[] = new AxisAlignedBB(
$this->x + ($connectWest ? 0 : $inset),
$this->y,
$this->z + $inset,
$this->x + 1 - ($connectEast ? 0 : $inset),
$this->y + 1.5,
$this->z + 1 - $inset
);
}
$connectNorth = $this->canConnect($this->getSide(Vector3::SIDE_NORTH));
$connectSouth = $this->canConnect($this->getSide(Vector3::SIDE_SOUTH));
if($connectNorth or $connectSouth){
//Z axis (north/south)
$bbs[] = new AxisAlignedBB(
$this->x + $inset,
$this->y,
$this->z + ($connectNorth ? 0 : $inset),
$this->x + 1 - $inset,
$this->y + 1.5,
$this->z + 1 - ($connectSouth ? 0 : $inset)
);
}
if(empty($bbs)){
//centre post AABB (only needed if not connected on any axis - other BBs overlapping will do this if any connections are made)
return [
new AxisAlignedBB(
$this->x + $inset,
$this->y,
$this->z + $inset,
$this->x + 1 - $inset,
$this->y + 1.5,
$this->z + 1 - $inset
)
];
}
return $bbs;
}
public function getFuelTime() : int{
return 300;
public function canConnect(Block $block){
return $block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent());
}
}

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,11 +36,11 @@ class FenceGate extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_AXE;
return BlockToolType::TYPE_AXE;
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
if(($this->getDamage() & 0x04) > 0){
return null;
@ -69,7 +68,7 @@ class FenceGate extends Transparent{
}
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$this->meta = ($player instanceof Player ? ($player->getDirection() - 1) & 0x03 : 0);
$this->getLevel()->setBlock($blockReplace, $this, true, true);

View File

@ -23,8 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\entity\Arrow;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Arrow;
use pocketmine\event\entity\EntityCombustByBlockEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageEvent;
@ -57,7 +57,7 @@ class Fire extends Flowable{
return false;
}
public function canBeReplaced(Block $with = null) : bool{
public function canBeReplaced() : bool{
return true;
}
@ -65,7 +65,7 @@ class Fire extends Flowable{
return true;
}
public function onEntityCollide(Entity $entity){
public function onEntityCollide(Entity $entity) : void{
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
$entity->attack($ev);
@ -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

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\math\AxisAlignedBB;
abstract class Flowable extends Transparent{
public function canBeFlowedInto() : bool{
@ -33,15 +35,11 @@ abstract class Flowable extends Transparent{
return 0;
}
public function getBlastResistance() : float{
return 0;
}
public function isSolid() : bool{
return false;
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return null;
}
}
}

View File

@ -29,15 +29,15 @@ use pocketmine\math\Vector3;
use pocketmine\Player;
class Flower extends Flowable{
const TYPE_POPPY = 0;
const TYPE_BLUE_ORCHID = 1;
const TYPE_ALLIUM = 2;
const TYPE_AZURE_BLUET = 3;
const TYPE_RED_TULIP = 4;
const TYPE_ORANGE_TULIP = 5;
const TYPE_WHITE_TULIP = 6;
const TYPE_PINK_TULIP = 7;
const TYPE_OXEYE_DAISY = 8;
public const TYPE_POPPY = 0;
public const TYPE_BLUE_ORCHID = 1;
public const TYPE_ALLIUM = 2;
public const TYPE_AZURE_BLUET = 3;
public const TYPE_RED_TULIP = 4;
public const TYPE_ORANGE_TULIP = 5;
public const TYPE_WHITE_TULIP = 6;
public const TYPE_PINK_TULIP = 7;
public const TYPE_OXEYE_DAISY = 8;
protected $id = self::RED_FLOWER;
@ -60,7 +60,7 @@ class Flower extends Flowable{
return $names[$this->meta] ?? "Unknown";
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$down = $this->getSide(Vector3::SIDE_DOWN);
if($down->getId() === Block::GRASS or $down->getId() === Block::DIRT or $down->getId() === Block::FARMLAND){
$this->getLevel()->setBlock($blockReplace, $this, true);
@ -82,4 +82,4 @@ class Flower extends Flowable{
return false;
}
}
}

View File

@ -24,22 +24,17 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ShortTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\Player;
use pocketmine\tile\FlowerPot as TileFlowerPot;
use pocketmine\tile\Tile;
class FlowerPot extends Flowable{
const STATE_EMPTY = 0;
const STATE_FULL = 1;
public const STATE_EMPTY = 0;
public const STATE_FULL = 1;
protected $id = self::FLOWER_POT_BLOCK;
protected $itemId = Item::FLOWER_POT;
@ -49,10 +44,10 @@ class FlowerPot extends Flowable{
}
public function getName() : string{
return "Flower Pot Block";
return "Flower Pot";
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return new AxisAlignedBB(
$this->x + 0.3125,
$this->y,
@ -63,29 +58,13 @@ class FlowerPot extends Flowable{
);
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if($this->getSide(Vector3::SIDE_DOWN)->isTransparent()){
return false;
}
$this->getLevel()->setBlock($blockReplace, $this, true, true);
$nbt = new CompoundTag("", [
new StringTag("id", Tile::FLOWER_POT),
new IntTag("x", $blockReplace->x),
new IntTag("y", $blockReplace->y),
new IntTag("z", $blockReplace->z),
new ShortTag("item", 0),
new IntTag("mData", 0)
]);
if($item->hasCustomBlockData()){
foreach($item->getCustomBlockData() as $key => $v){
$nbt->{$key} = $v;
}
}
Tile::createTile(Tile::FLOWER_POT, $this->getLevel(), $nbt);
Tile::createTile(Tile::FLOWER_POT, $this->getLevel(), TileFlowerPot::createNBT($this, $face, $item, $player));
return true;
}
@ -112,19 +91,17 @@ class FlowerPot extends Flowable{
$this->setDamage(self::STATE_FULL); //specific damage value is unnecessary, it just needs to be non-zero to show an item.
$this->getLevel()->setBlock($this, $this, true, false);
$pot->setItem($item);
$pot->setItem($item->pop());
if($player instanceof Player){
if($player->isSurvival()){
$item->setCount($item->getCount() - 1);
$player->getInventory()->setItemInHand($item->getCount() > 0 ? $item : ItemFactory::get(Item::AIR));
}
}
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){
@ -137,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,10 +36,14 @@ class GlazedTerracotta extends Solid{
}
public function getToolType() : int{
return Tool::TYPE_PICKAXE;
return BlockToolType::TYPE_PICKAXE;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
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{
if($player !== null){
$faces = [
0 => 4,
@ -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)
];
}
@ -76,22 +75,22 @@ class Grass extends Solid{
return Level::BLOCK_UPDATE_RANDOM;
}elseif($lightAbove >= 9){
//try grass spread
$vector = $this->asVector3();
for($i = 0; $i < 4; ++$i){
$vector->x = mt_rand($this->x - 1, $this->x + 1);
$vector->y = mt_rand($this->y - 3, $this->y + 1);
$vector->z = mt_rand($this->z - 1, $this->z + 1);
$x = mt_rand($this->x - 1, $this->x + 1);
$y = mt_rand($this->y - 3, $this->y + 1);
$z = mt_rand($this->z - 1, $this->z + 1);
if(
$this->level->getBlockIdAt($vector->x, $vector->y, $vector->z) !== Block::DIRT or
$this->level->getFullLightAt($vector->x, $vector->y + 1, $vector->z) < 4 or
BlockFactory::$lightFilter[$this->level->getBlockIdAt($vector->x, $vector->y + 1, $vector->z)] >= 3
$this->level->getBlockIdAt($x, $y, $z) !== Block::DIRT or
$this->level->getBlockDataAt($x, $y, $z) === 1 or
$this->level->getFullLightAt($x, $y + 1, $z) < 4 or
BlockFactory::$lightFilter[$this->level->getBlockIdAt($x, $y + 1, $z)] >= 3
){
continue;
}
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($this->level->getBlock($vector), $this, BlockFactory::get(Block::GRASS)));
$this->level->getServer()->getPluginManager()->callEvent($ev = new BlockSpreadEvent($b = $this->level->getBlockAt($x, $y, $z), $this, BlockFactory::get(Block::GRASS)));
if(!$ev->isCancelled()){
$this->level->setBlock($vector, $ev->getNewState(), false, false);
$this->level->setBlock($b, $ev->getNewState(), false, false);
}
}

View File

@ -25,8 +25,9 @@ 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;
class GrassPath extends Transparent{
@ -41,10 +42,10 @@ class GrassPath extends Transparent{
}
public function getToolType() : int{
return Tool::TYPE_SHOVEL;
return BlockToolType::TYPE_SHOVEL;
}
protected function recalculateBoundingBox(){
protected function recalculateBoundingBox() : ?AxisAlignedBB{
return new AxisAlignedBB(
$this->x,
$this->y,
@ -59,9 +60,18 @@ class GrassPath extends Transparent{
return 0.6;
}
public function getDrops(Item $item) : array{
public function onUpdate(int $type){
if($type === Level::BLOCK_UPDATE_NORMAL and $this->getSide(Vector3::SIDE_UP)->isSolid()){
$this->level->setBlock($this, BlockFactory::get(Block::DIRT), true);
return $type;
}
return false;
}
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

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\PillarRotationHelper;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\Player;
@ -43,17 +44,8 @@ class HayBale extends Solid{
return 0.5;
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $facePos, Player $player = null) : bool{
$faces = [
0 => 0,
1 => 0,
2 => 0b1000,
3 => 0b1000,
4 => 0b0100,
5 => 0b0100
];
$this->meta = ($this->meta & 0x03) | $faces[$face];
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
$this->getLevel()->setBlock($blockReplace, $this, true, true);
return true;
@ -62,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 [];
}
}

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