Compare commits

...

257 Commits

Author SHA1 Message Date
aaa01bb6f8 Release 3.9.1 2019-07-14 19:10:29 +01:00
50d71809e1 Entity: fixed onfire flag being set when setting fire ticks to zero, closes #3031 2019-07-14 19:03:06 +01:00
6839712394 added new PlayerActionPacket constant, silence debug noise every time a player clicks a block 2019-07-14 17:30:37 +01:00
9b5ae7ec75 regenerate LevelSoundEventPacket sound IDs 2019-07-14 17:28:29 +01:00
94eb64c2be 1.12: fix resource packs, closes #3023 2019-07-14 17:22:44 +01:00
3fae57508b update particle ids 2019-07-13 20:08:17 +01:00
a883c35fd0 clean up yesterday's mess 2019-07-13 18:15:14 +01:00
740398282f [ci skip] added some detail about packet changes in 3.9.0 release 2019-07-13 15:35:00 +01:00
9d14bc54d6 3.9.1 is next 2019-07-12 19:03:24 +01:00
bd69c66d03 Release 3.9.0 2019-07-12 19:03:23 +01:00
c58a1bf9b7 Protocol changes for 1.12.0.28 2019-07-12 19:00:15 +01:00
59c310b914 unfuck the make-release script 2019-07-12 18:59:54 +01:00
790fcc4ebb Release 3.8.7 2019-07-12 18:20:47 +01:00
5430f19e7a make-release: allow specifying a version number explicitly 2019-07-12 18:18:26 +01:00
1cf4cf8614 Fixed decoding entries in SetScorePacket
closes #3000
2019-07-09 15:49:24 +01:00
55cccff850 Player: fixed documentation of isValidUserName()
[ci skip]
2019-07-07 23:50:59 +01:00
03e70e68f4 Player: fixed documentation of getDisplayName()
[ci skip]
2019-07-07 23:49:11 +01:00
7c52b4c93d make-release: added a missing newline 2019-07-07 18:02:25 +01:00
3f31dbde57 3.8.7 is next 2019-07-07 17:49:37 +01:00
1bfd6f2a90 Release 3.8.6 2019-07-07 17:49:37 +01:00
c7a5b8b0b4 Fixed noDamageTicks not preventing damage when last damage cause is null
noDamageTicks should make the entity completely invulnerable while active.
2019-07-07 17:37:52 +01:00
11fc16617a Liquid: fix max cost calculation for flow direction search, closes #2995 2019-07-07 14:32:52 +01:00
77a4393c7b Fixed possible out-of-bounds access on corrupted playerdata when loading inventory contents 2019-07-06 19:39:07 +01:00
f714ed6e90 Generator: fixed incorrect negative seed parsing in convertSeed() 2019-07-05 19:20:21 +01:00
7fc45bc5c3 partial fix for #2986 2019-07-04 18:18:42 +01:00
ab4b1be363 add constants for boat action of AnimatePacket
closes #2991
2019-07-03 16:30:45 +01:00
3c7f68dc1e Fix Entity::isNameTagAlwaysVisible() was returning the wrong value (#2990)
* Fix Entity::isNameTagAlwaysVisible() was returning the wrong value

* "> 0" to "=== 1"
2019-07-02 10:44:41 +01:00
15fa1056b7 added make-release script 2019-06-25 18:03:48 +01:00
feac2df088 readme: point to /plugins on poggit
[ci skip]
2019-06-25 13:11:36 +01:00
4c2015fd0f Update README.md
[ci skip]
2019-06-25 10:48:11 +01:00
16482e6a95 Update README.md
[ci skip]
2019-06-25 10:46:44 +01:00
ae9115ad0d 3.8.6 is next 2019-06-24 14:55:38 +01:00
6b090d653c Release 3.8.5 2019-06-24 14:55:38 +01:00
012f015e7d [ci skip] update changelog md for 3.8.5 2019-06-24 14:25:47 +01:00
6925451f3f StartGamePacket: added rogue field
this was added after 1.11.0 without a protocol version bump.
2019-06-22 20:25:50 +01:00
46054803d5 [ci skip] tinkering with readme logo alignment 2019-06-19 14:04:30 +01:00
a9f99240b5 readme: even less noise [ci skip] 2019-06-19 13:57:20 +01:00
a16b44ea12 readme: reduce useless noise [ci skip] 2019-06-19 13:51:16 +01:00
cd48d8272c added changelog for 3.8.5 2019-06-16 17:17:21 +01:00
6d09460abc Merge branch 'changelogs' into stable 2019-06-16 17:12:57 +01:00
0ca07ad075 Fire QueryRegenerateEvent every 1 second instead of every 25, fixes #2670 2019-06-16 16:17:06 +01:00
60b183b0d9 backport a753c1342: Clean up Query cache handling, remove useless timeouts
the timeout was entirely useless, because:
- when shorter than 25.6 seconds (512 ticks) it would cause caches to be needlessly destroyed and regenerated
- when longer than 25.6 seconds, just made outdated caches persist for longer, even after the query info was regenerated.

This now uses a mark-dirty model to deal with caches, which means that plugin modifications to the query data will be reflected immediately, regardless of when they are made. Previously, modifying the result of Server->getQueryInformation() would have inconsistent results.
2019-06-16 16:08:27 +01:00
dbf4054b1f backport 209135492: UUID: add type docs 2019-06-16 14:44:13 +01:00
82e4ef6d48 backport d8c81c0a1: UUID: remove useless default values
these are overwritten by the constructor, so they have no use here.
2019-06-16 14:43:28 +01:00
d0d300a6f8 backport 342b48b75: VersionString: Use the correct bitwise operators 2019-06-16 14:21:02 +01:00
6161155660 CraftingManager: micro optimization: reuse closure for item deserialize & reduce indirection 2019-06-16 14:05:37 +01:00
2a5561fcd1 added more MultiRecipe UUIDs 2019-06-15 19:51:59 +01:00
5d531b56db travis.sh: lock down PHPUnit at 7.5.11
7.5.12 makes changes which assume libxml is present, which isn't the case with our PHP builds.
2019-06-14 16:58:56 +01:00
3568c7b1c7 Merge branch 'stable' of https://github.com/pmmp/PocketMine-MP into stable 2019-06-13 16:05:18 +01:00
862c844759 Write PID into lock file 2019-06-13 15:11:59 +01:00
42954c1d72 Server: document the crazy behaviour of some innocent looking functions 2019-06-12 10:14:29 +01:00
4c5f6eb1b7 Moved preprocessor submodule to build/ directory 2019-06-11 17:56:13 +01:00
02bc43b440 missed a bit 2019-06-11 16:48:24 +01:00
5832f42783 added changelogs as mdfiles 2019-06-11 16:44:05 +01:00
7c1f038f20 3.8.5 is next 2019-06-10 17:56:23 +01:00
a42f68d3cf Release 3.8.4 2019-06-10 17:55:50 +01:00
b6f3f6120b InventoryTransaction: Shuffle actions on execution to prevent plugins relying on the order
closes #2955
2019-06-10 17:24:16 +01:00
96d3f4f78b Updated documentation for transaction classes 2019-06-10 17:19:03 +01:00
6756203aec InventoryTransaction: Added a warning about ordering 2019-06-10 16:54:45 +01:00
adb78679c5 Added link to docker image 2019-06-09 18:47:04 +08:00
b60731607d Update travis.sh 2019-06-06 17:20:16 +01:00
0058bfcd23 Utils: Limit length of printed stack trace strings to 80 characters 2019-06-06 14:56:19 +01:00
9f31b479e1 Improve stack trace rendering, show array and string lengths 2019-06-06 14:53:50 +01:00
eb161f8e1c Use base64 instead of hex to display binary in some places
base64 takes less space than hex, which is beneficial for logging larger payloads.
2019-06-06 14:43:20 +01:00
80f8a27094 Fixed implicit dependency on MobArmorEquipmentPacket field ordering
the order of the slots is entirely dependent on Mojang whims, so we shouldn't let our internals rely on it.
2019-06-04 18:16:56 +01:00
341c480e13 ContainerSetDataPacket: added missing furnace property ID 2019-06-03 18:21:29 +01:00
971ad04299 Attribute: add more things
i got tired of commenting out exceptions in packets, so this is the quickest way to fix the problem.
2019-06-03 17:37:18 +01:00
025b72e2f2 Randomize the order of plugins retrieved from disk, fixes #2945 (#2948)
On most filesystems, plugins are loaded in lexical order because that's how the filesystem gives the files to us. This is a problem because it can hide bugs with dependency resolution on specific platforms with this behaviour, while inexplicably breaking on other platforms where the load order is different or undefined.

This change prevents plugins depending on any file yield order by randomizing the order in which plugin files are checked for loadability.
2019-05-31 17:11:20 +01:00
cf538afb84 LevelEventPacket: added two extra IDs 2019-05-31 15:31:03 +01:00
7ff91337ad 3.8.4 is next 2019-05-27 19:01:06 +01:00
63e5867727 Release 3.8.3 2019-05-27 18:59:56 +01:00
c38779f1fd Block: fixed use of full meta as variant in several cases
fixes #2940

now I need to go to the bathroom and wash this off my hands ... I'd forgotten how nasty this code is
2019-05-27 18:04:25 +01:00
14bae72dd5 Create FUNDING.yml 2019-05-27 14:14:09 +01:00
f35b43613d IronTrapdoor: fixed fuel time, closes #2914
this should be removed during branch merge.
2019-05-24 17:31:36 +01:00
3d0fa10437 Stonecutter: fix hardness, close #2915 2019-05-24 17:30:20 +01:00
76e5ea385b Skin: improved error checking
plugin devs should find this less of a pain in the ass now.
2019-05-17 17:40:27 +01:00
5a351d3caf Fix for Server::hasOfflinePlayerData (#2919) 2019-05-12 12:06:05 +01:00
bb93d4f8de TimeCommand: Fix commands.time.query message (#2917) 2019-05-12 09:21:39 +01:00
66818e178a DefaultPermissions: Fix typos in permission descriptions (#2918) 2019-05-12 09:20:45 +01:00
f782a478c4 Player: clarify resetTitles() documentation 2019-05-08 17:03:40 +01:00
c06b4830d1 Player: don't spawn entities on out-of-sync chunks on join, closes #2911 2019-05-08 15:36:54 +01:00
6d64ef8d74 Server: fixed crash reporting bug introduced by a6e5b6e158 2019-05-05 20:52:52 +01:00
c5498bb3fa Implement a locking variable to circumvent a infinite regression (#2901)
closes #2876
2019-05-03 14:46:51 +01:00
59334d652f 3.8.3 is next 2019-05-02 17:13:50 +01:00
5c81da9b1e Release 3.8.2 2019-05-02 17:13:21 +01:00
b08affc4c6 Updated preprocessor submodule 2019-05-02 17:11:40 +01:00
cb49f1e835 fixed air being breakable by creative players
closes #2851
2019-05-02 16:25:23 +01:00
f6a0f4aa82 Player: fixed immobile interference on PlayerJoinEvent
closes #2894

this should use a cleaner hack that doesn't affect plugins at all, but that's too much work for this one bug fix.
2019-05-02 16:20:28 +01:00
de09c8c082 Player: fix crash handling resource pack requests 2019-05-02 16:17:39 +01:00
0ac87989dc Update RakLib to 0.12.4 2019-05-02 16:08:03 +01:00
13ea984b12 Server: setup world things at a more appropriate time
closes #2859

this also fixes reported headaches attempting to override generators before world load.
2019-05-02 15:02:10 +01:00
3878f58847 Level: fixed crash when time overflows
this can be triggered by a plugin setting time to PHP_INT_MAX

fixes CA 2346977
2019-05-02 14:22:01 +01:00
d7a35a5302 Entity: fixed motion not being initialized when Motion NBT tag is missing
fixes CA 2355485
2019-05-02 14:00:28 +01:00
d850a84d0d Level: clean up and remove checkTime() 2019-04-26 14:15:41 +01:00
22d9260a3b remove unused import 2019-04-26 13:56:32 +01:00
3c90ed13b9 NoteBlock: added //TODO 2019-04-26 12:45:08 +01:00
396efbac7e Human: simplify setFood() 2019-04-26 12:40:15 +01:00
00644dd529 Fixed an edge-case in AvailableCommandsPacket decoding 2019-04-26 12:32:42 +01:00
c2c210e25a Fixed --enable-ansi and --disable-ansi not being respected on threads
this causes some breakage to the behaviour of Terminal, and for that reason this is going on 4.0.

Terminal::hasFormattingCodes() will no longer auto-detect whether colour codes are supported.
2019-04-26 12:30:24 +01:00
86c4e936cb Player now drops the contents of temporary inventories
these inventories are just glorified crafting tables.
2019-04-26 12:27:52 +01:00
3b103dcd62 Level: use isInWorld() where appropriate 2019-04-26 12:26:01 +01:00
48dfc5b232 Level: reduce complexity of populateChunk() 2019-04-26 12:18:00 +01:00
39360f127a Player: Don't use iusername in cases where it's useless
these calls all do strtolower() anyway, so having iusername here just makes it confusing.
2019-04-26 12:07:47 +01:00
25890e76e2 Player: replace redundant usage of Server->broadcast() 2019-04-26 12:04:56 +01:00
810bdeb965 Test one extra case for LevelProviderManager 2019-04-26 12:01:12 +01:00
b6b3dcc1aa Improve documentation of SourceInterface and AdvancedSourceInterface 2019-04-26 11:59:10 +01:00
e0818e7e52 reorganize and optimize start.sh (#2267) 2019-04-26 11:54:50 +01:00
d0c4463773 3.8.2 is next 2019-04-26 10:08:59 +01:00
7521160f53 Release 3.8.1 2019-04-26 10:08:22 +01:00
4f5190e3f8 Updated BedrockData submodule 2019-04-25 20:53:08 +01:00
3c941dd992 Move more stuff to BedrockData submodule 2019-04-25 18:23:31 +01:00
89f457b397 updated legacy ID table (thanks @MCMrARM) 2019-04-25 17:49:10 +01:00
2bdbb9794c New, more efficient blockstate table format
this reduces the file size by ~90%.
2019-04-25 17:28:22 +01:00
898009a91b Sync crafting data changes
this seems to fix #2881, at least the reproducing case that was given.
2019-04-25 16:22:12 +01:00
793f93afdb NetworkSession: sync with latest code generation changes 2019-04-25 14:49:20 +01:00
64506ea3ae PacketPool: add @throws 2019-04-25 14:48:55 +01:00
4a35516441 Reduce BatchPacket hacks
we can't get rid of these hacks entirely because BAcKWARdS ComPaTIbilitY, but this at least ensures that things over PID 127 won't burn the house down when 1.12 gets here. This also reduces conflicts with 4.0 line.
2019-04-25 14:48:36 +01:00
74b9922a28 3.8.1 is next 2019-04-24 20:00:58 +01:00
088fbf65b1 Release 3.8.0 2019-04-24 19:54:57 +01:00
fa70127241 1.11.0 protocol changes 2019-04-24 19:54:16 +01:00
fc76d04dcb StartGamePacket: allow specifying a custom runtimeID table
this is not the intended goal, but it's a happy side effect of making it easier to extract structured information from the client.
2019-04-24 18:40:29 +01:00
15ae323bcb doxygen: updated config file 2019-04-23 17:58:24 +01:00
353bae87a7 3.7.4 is next 2019-04-23 17:14:49 +01:00
dc7be3fd52 Release 3.7.3 2019-04-23 17:13:04 +01:00
f28a0740a0 Move version info to its own file for easier third party tooling 2019-04-23 16:07:25 +01:00
df990fb47a disable C preprocessing (this will just cause unwanted bugs) 2019-04-23 15:43:39 +01:00
98ca28d96e add a warning when chunkutils is missing 2019-04-21 17:36:38 +01:00
db896b9faf ok i'm done
i am obviously not in any fit state to be doing this today...
2019-04-21 14:22:54 +01:00
76c234e4e6 add some limits on batches 2019-04-21 14:16:38 +01:00
2ef3962028 sync RakLib dependency 2019-04-21 13:24:19 +01:00
1e5941c98c Level: Properly report world save timings
this wasn't including chunk unloading in the world save timings.
2019-04-18 19:39:23 +01:00
9ca7c0c883 3.7.3 is next 2019-04-15 18:45:53 +01:00
b4a8f8391b Release 3.7.2 2019-04-15 18:45:16 +01:00
142d750b9f TextFormat: clean() now removes private-use area Unicode characters
the console can't print these, and these are being abused to cause mass crashes in the wild.
2019-04-15 18:42:09 +01:00
948b0b4cbc Add an API change request template 2019-04-15 08:49:31 +01:00
d6b596a8ac moar issue templates 2019-04-15 08:49:16 +01:00
eab2d4d704 Add a Support issue template
maybe this will guide people who don't read into shooting themselves in the foot automatically >:)
2019-04-15 08:49:01 +01:00
8114551600 add a Crash issue template
valid crashdumps are usually self explanatory and include all required information like OS/version/etc, so there's no need to force reporters to rewrite a bunch of extra information that should already be in the crashdump.
2019-04-15 08:48:45 +01:00
8e1d1993c5 Update support.yml 2019-04-15 08:48:31 +01:00
82bf5f6193 Add Discord link to issue template 2019-04-15 08:48:16 +01:00
76a86e51f7 Remove legacy issue template 2019-04-15 08:47:58 +01:00
d1e803685a Update issue templates 2019-04-15 08:47:42 +01:00
0a884aa5fb Support bot: Be a little less rude 2019-04-15 08:47:32 +01:00
c410e676b3 Update ISSUE_TEMPLATE.md 2019-04-15 08:47:18 +01:00
8f1f5fde47 Security vulnerability reporting for dummies 2019-04-15 08:46:59 +01:00
0f268df2e0 Add community Discord to Discussion section 2019-04-14 22:57:13 +01:00
86108e7010 Added donation methods 2019-04-14 22:57:00 +01:00
5ea448ef36 Add ExamplePlugin to README 2019-04-14 22:56:49 +01:00
389e7767d1 Sign: apply a very stupid limit on text size
this is necessary because of the epidemic of server attacks going around lately.
2019-04-14 19:30:28 +01:00
4c268acc00 Fixed /whitelist on/off permissions, closes #2849 2019-04-14 17:58:53 +01:00
e34a4f6b98 Added server.lock into .gitignore
closes #2868
2019-04-13 14:26:47 +01:00
3925e598d6 Acquire exclusive lock on <datadir>/server.lock to avoid data corruption (#2858)
this fixes #2855.
2019-04-08 20:31:24 +01:00
383ec8a8e3 TextFormat: Fixed tokenize() not being Unicode-aware 2019-04-08 15:45:26 +01:00
95313e0a90 Updated some entity metadata properties 2019-04-08 14:42:33 +01:00
e9a87978a6 Fixed usages of commands.generic.permission
apparently this doesn't exist in the client anymore
2019-04-07 15:07:24 +01:00
612e9e162c Fixed worlds with unknown generators silently getting wrong generator, closes #2860 2019-04-06 15:17:36 +01:00
fdc3faadc9 Register two missing default permissions
this fixes the pocketmine.command node not having the expected effect in some cases.
2019-04-05 18:48:37 +01:00
9644e72acf Doxygen: added index page 2019-04-05 09:35:25 +01:00
2c678dcf0d Player: Fixed memory leak when PlayerLoginEvent is cancelled 2019-04-03 17:37:15 +01:00
7bd9a2b2e0 3.7.2 is next 2019-03-30 19:15:17 +00:00
5c26deb517 Release 3.7.1 2019-03-29 19:56:06 +00:00
8fcb44de7d Merge branch '3.6' into 3.7 2019-03-29 19:55:36 +00:00
bd2e7db3b9 Release 3.6.6 2019-03-29 19:49:30 +00:00
f4480c07ee Updated NBT dependency 2019-03-29 19:47:15 +00:00
c09e2301c8 Merge branch '3.6' into 3.7 2019-03-29 14:35:35 +00:00
8e9f787d33 Implement runtimeID table randomization, closes #2841 2019-03-29 14:35:06 +00:00
89833b3b68 Merge branch '3.6' into 3.7 2019-03-26 15:01:59 +00:00
a10a656a5d Network: add a README to mcpe namespace 2019-03-26 15:01:00 +00:00
2659ed8d91 AvailableCommandsPacket: Updated the argument type constants for 1.10. (#2824) 2019-03-22 15:07:15 +00:00
9c01ecbe7e Merge branch '3.6' into 3.7 2019-03-21 19:02:20 +00:00
6a55021779 Flat: Allow asterisk in preset layers
closes #2818
2019-03-21 18:59:50 +00:00
6ada261b04 3.7.1 is next 2019-03-20 19:39:36 +00:00
14a6779e08 Release 3.7.0 2019-03-20 19:17:41 +00:00
cce99b07af 1.10.0 updates 2019-03-20 19:17:41 +00:00
c3d80d711d Fixed autosave time report measurement not using correct unit (as per master) 2019-03-20 19:01:10 +00:00
1a8b33dafe AvailableCommandsPacket: Updated the ARG_TYPE constants
closes #2817
2019-03-18 08:58:07 +00:00
baa094a2d1 3.6.6 is next 2019-03-10 11:49:31 +00:00
f2ff510597 Release 3.6.5 2019-03-10 11:49:06 +00:00
562179bdd6 Backport 58cafc853f: s/level/world (strings only)
we should look at doing this for code too, but for now I'm not planning to break everyone's plugins.
2019-03-10 11:35:46 +00:00
5c12bee874 Backport other part of 2bffd5cc1c: Add timer measurements for autosave 2019-03-10 11:20:51 +00:00
99606bbe23 beware possible API break 2019-03-09 19:33:46 +00:00
a1d50de12e OOF 2019-03-09 19:31:13 +00:00
4252c5914b Backport 93cd00ae8f: Remove dead settings from pocketmine.yml 2019-03-09 19:21:39 +00:00
0659d2fbef Backport 6bd43a8215: Firehose auto-tick-rate anti-feature, closes #2665 2019-03-09 19:20:53 +00:00
10612acace Partial backport of 2bffd5cc1c to 3.6 2019-03-09 19:10:09 +00:00
1d810f8aeb Backport c3e66e0adc to 3.6 2019-03-09 19:09:05 +00:00
414104851a LevelDB: Mark chunks as changed when upgraded from an older chunk format 2019-03-09 19:02:34 +00:00
c0bed03a2a Update PlayerRespawnEvent.php (#2797)
removed obsolete comment
2019-03-05 16:28:58 +00:00
d25c84acff Fixed RegionLoader corrupting location table when too-large chunks are discovered
this was making the location table point to an offset that did not yet exist, which caused the region header consistency check to discard the region as corrupted the next time it was loaded.
2019-03-05 12:09:27 +00:00
55994e08db RegionLoader: make some error messages more detailed 2019-03-05 11:18:02 +00:00
6f5d4d6b80 RegionLoader: fixed handling of invalid chunk coordinates 2019-03-05 10:52:36 +00:00
df1ef7fe0c Improve RegionLoader tests 2019-03-05 10:51:44 +00:00
20a25a69df Force emission of output buffer contents on crash 2019-03-04 12:01:30 +00:00
faca610594 NetworkBinaryStream: remove dead field 2019-03-03 12:38:03 +00:00
91603dc2d6 3.6.5 is next 2019-03-03 11:50:10 +00:00
af90e18b18 Release 3.6.4 2019-03-03 11:49:07 +00:00
ab5b4d112b BaseInventory: fixed items with userdata stacking with items without userdata 2019-03-03 11:12:36 +00:00
a30b1fb6d5 Inventory: Add failing test case for itemstack NBT duplication 2019-03-03 11:11:33 +00:00
20b4723728 Player: fixed held slot being out of sync after dying, closes #2788
it appears this premature optimization dates back to the days when PlayerHotbarPacket was not useless.
2019-02-27 09:26:56 +00:00
d1ced0ffc6 Player: fixed XP not dropping on death 2019-02-27 09:22:52 +00:00
2164dbae67 Fixed reloaded arrows not despawning, closes #2781 2019-02-26 19:58:21 +00:00
6c92a2e88b Ladder: be more strict about resetting fall distance
closes #2790
2019-02-26 19:54:57 +00:00
97deadc59f PackedIce: fixed dropping without silk touch, closes #2789 2019-02-26 19:48:18 +00:00
0c3b136a8d Player: fixed removeWindow() sometimes removing GUI / crashing clients 2019-02-24 12:14:19 +00:00
79b7e08e60 Silence NetworkStackLatencyPacket spam from dev builds 2019-02-23 11:03:50 +00:00
2540dacdd7 PluginManager: fixed suffix split handling 2019-02-23 10:51:06 +00:00
f1078e3909 3.6.4 is next 2019-02-22 18:07:48 +00:00
2f43b054de Release 3.6.3 2019-02-22 18:07:00 +00:00
23b5d64535 Merge branch '3.5' into 3.6 2019-02-22 18:03:51 +00:00
9afa0e5483 Release 3.5.13 2019-02-22 17:56:44 +00:00
4eaea54b0e TaskScheduler: fixed wrong typehints
These methods never return null.
2019-02-22 17:47:28 +00:00
6b51bf4a80 Merge branch '3.5' into 3.6 2019-02-18 13:11:16 +00:00
cba8d86c4f Fixed Fire Aspect not working on TNT 2019-02-18 13:11:08 +00:00
2e834c8f5c Merge branch '3.5' into 3.6 2019-02-17 16:10:47 -05:00
f9873e9108 ItemFrame: fixed hardness 2019-02-17 16:10:21 -05:00
074baf7e1c Merge branch '3.5' into 3.6 2019-02-17 17:08:15 +00:00
2e0dd574e0 Set default health attribute value when changing max health, closes #2771 2019-02-17 17:06:32 +00:00
e16d8e31af Merge branch '3.5' into 3.6 2019-02-17 11:33:46 +00:00
3c93a57397 Entity: add a hack to prevent client-side movement when entity is not moving
this fixes #2227.
2019-02-17 11:33:34 +00:00
e2e927b328 3.6.3 is next 2019-02-14 17:17:18 +00:00
a8dab25201 Release 3.6.2 2019-02-14 17:15:19 +00:00
3de2b7969e Merge branch '3.5' into 3.6 2019-02-14 17:14:59 +00:00
8f486ea65d 3.5.13 is next 2019-02-14 17:14:34 +00:00
6b971b1761 Release 3.5.12 2019-02-14 16:55:44 +00:00
6f36fa504b TextFormat: make clean() less confusing, deduplicate some regex 2019-02-14 16:52:39 +00:00
8e73842a93 Player: work around 1.9 command casing crash bug, closes #2761 2019-02-14 16:17:17 +00:00
e71e18fc88 Merge branch '3.5' into 3.6 2019-02-14 16:02:30 +00:00
e1bacb5c6d Human: fixed hunger underflow when value is a fraction, closes #2761 2019-02-14 16:01:25 +00:00
44697e784a Sign: add validity checks on text encoding, scrub invalid UTF-8 on load
this works around a bug where corrupted text on preexisting signs can mess up the client. This also prevents corrupted text getting onto signs in the future by having them scrubbed and validated before applying them.
2019-02-14 15:16:51 +00:00
65529ff2ce Command: add @throws CommandException 2019-02-14 15:09:41 +00:00
c346c45d42 Use regex for command argument parsing, fixes #2266
moral of the story: don't abuse functions for things they weren't designed for... lol
2019-02-14 15:07:58 +00:00
c433fad0a7 another /u modifier 2019-02-14 13:50:56 +00:00
8fad5a6e30 TextFormat: use mb_scrub() in clean()
this redacts invalid characters to prevent them appearing in places that might break the client.
2019-02-13 20:01:36 +00:00
7a6f279825 TextFormat: fixed clean() not being unicode-aware 2019-02-13 17:06:44 +00:00
10b72c895d Merge branch '3.5' into 3.6 2019-02-13 14:53:00 +00:00
d520928888 Fixed startup time measurement, closes #2713, closes #2750 2019-02-13 14:50:52 +00:00
27767e7ddb Verify player name command input, closes #2729, closes #2749 2019-02-13 14:50:43 +00:00
243c12de7c EffectCommand: fix bounds check, closes #2055 2019-02-13 14:37:40 +00:00
372545e47e Merge branch '3.5' into 3.6 2019-02-12 16:56:53 +00:00
8913b48700 "Implement" info-update and reserved6 2019-02-12 16:56:12 +00:00
6ee4a0e090 Implement invisible bedrock to fix placement issues
I don't know why this wasn't done a long time ago, but here it is.
2019-02-12 16:41:23 +00:00
8bd8da4bc6 Merge branch '3.5' into 3.6 2019-02-10 17:15:48 +00:00
9ba4144a71 Server: remove useless gc_collect_cycles()
the server is shutting down at this point so who cares if there are cycles...
2019-02-10 17:15:41 +00:00
9da7c6af27 new metadata properties 2019-02-10 13:59:21 +00:00
109312284c 3.6.2 is next 2019-02-08 16:41:10 +00:00
51934614bc Release 3.6.1 2019-02-08 16:40:38 +00:00
9e89f65094 Fixed handling for some new blocks which slipped through the frontline 2019-02-08 16:38:17 +00:00
9562711b84 Updated BedrockData submodule to 1.9.0 2019-02-08 15:32:57 +00:00
30b49e0d22 Merge branch '3.5' into 3.6 2019-02-08 15:32:20 +00:00
a975868fc3 3.5.12 is next 2019-02-08 13:52:31 +00:00
b38b932845 Release 3.5.11 2019-02-08 13:52:09 +00:00
43cb19ebca Updated bedrockData submodule to 1.8.0 2019-02-08 13:51:41 +00:00
769cc91543 ItemFactory: fix crash when getting negative item IDs
these are now treated the same as any unknown item, and are now not possible to place.
2019-02-08 13:51:41 +00:00
278f37d3e0 3.6.1 is next 2019-02-07 22:07:31 +00:00
02a6ca84a9 Releass 3.6.0 2019-02-07 22:06:33 +00:00
b8703d5dff Protocol changes for 1.9.0 2019-02-07 21:56:42 +00:00
37c2d78731 3.5.11 is next 2019-02-07 20:47:05 +00:00
199 changed files with 7556 additions and 1451 deletions

8
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,8 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: pocketminemp
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
custom: https://github.com/pmmp/PocketMine-MP#donate

View File

@ -1,48 +0,0 @@
### Issue description
<!---
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.
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. ...
2. ...
### OS and versions
<!--- use the 'version' command in PocketMine-MP
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 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.
-->
* PocketMine-MP: <!-- LATEST IS NOT A VALID VERSION -->
* PHP:
* Server OS:
* Game version: PE/Win10 (delete as appropriate)
### Plugins
- Test on a clean server without plugins: is the issue reproducible without any plugins loaded?
If the issue is **not** reproducible without plugins:
- Have you asked for help on our forums before creating an issue?
- Can you provide sample, *minimal* reproducing code for the issue? If so, paste it in the bottom section
- Paste your list of plugins here (use the 'plugins' command in PocketMine-MP)
### Crashdump, backtrace or other files
- Do not paste crashdumps into an issue - please use our Crash Archive at https://crash.pmmp.io for submitting crash reports to not spam the issue tracker. Add links to your reports in the Crash Archive here.
- Please use gist or anything else to add other files and add links here
* ...

View File

@ -0,0 +1,19 @@
---
name: API change request
about: Suggest a change, addition or removal to the plugin API
title: ''
labels: ''
assignees: ''
---
<!--- tell us what you want -->
## Description
<!--- explain why you want this and why it's a good idea -->
## Justification
<!--- (optional) describe alternative methods you've explored to achieve your goal -->
## Alternative methods

36
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,36 @@
---
name: Bug report
about: Unexpected non-crash behaviour (except missing gameplay features)
title: ''
labels: ''
assignees: ''
---
### Issue description
- Expected result: What were you expecting to happen?
- Actual result: What actually happened?
### Steps to reproduce the issue
1. ...
2. ...
### OS and versions
<!-- try the `version` command | LATEST IS NOT A VALID VERSION -->
* PocketMine-MP:
* PHP:
* Server OS:
* Game version: PE/Win10 (delete as appropriate)
### Plugins
<!--- use the `plugins` command and paste the output below -->
- If you remove all plugins, does the issue still occur?
- If the issue is **not** reproducible without plugins:
- Have you asked for help on our forums before creating an issue?
- Can you provide sample, *minimal* reproducing code for the issue? If so, paste it in the bottom section
### Crashdump, backtrace or other files
<!--- Submit crashdumps at https://crash.pmmp.io and paste a link -->
<!--- Use gist or anything else to add other files and add links here -->

15
.github/ISSUE_TEMPLATE/crash.md vendored Normal file
View File

@ -0,0 +1,15 @@
---
name: Crash
about: Report a crash in PocketMine-MP (not plugins)
title: Server crashed
labels: ''
assignees: ''
---
<!--- submit crashdump files to https://crash.pmmp.io -->
<!--- or, copy the data between ===BEGIN CRASH DUMP=== and ===END CRASH DUMP and paste it on a site like https://pastebin.com -->
Link to crashdump:
<!--- write additional information about the crash to help us find the problem -->
### Additional comments (optional)

View File

@ -0,0 +1,14 @@
---
name: Help & support
about: We don't accept support requests here. Try the links on the README.
title: ''
labels: Support request
assignees: ''
---
We don't accept support requests on the issue tracker. Please try the following links instead:
Documentation: http://pmmp.rtfd.io
Forums: https://forums.pmmp.io
Discord: https://discord.gg/bge7dYQ

View File

@ -0,0 +1,12 @@
---
name: Security/DoS vulnerability
about: 'Bug or exploit that can be used to attack servers (hint: don''t report it
on a public issue tracker)'
title: ''
labels: 'Auto: Spam'
assignees: ''
---
Please DO NOT report security vulnerabilities here.
Instead, send an email to team@pmmp.io or contact a developer directly, IN PRIVATE.

6
.github/support.yml vendored
View File

@ -5,7 +5,11 @@ supportLabel: "Support request"
# Comment to post on issues marked as support requests. Add a link
# to a support page, or set to `false` to disable
supportComment: >
This issue tracker is not a support forum. Please use the [forums](https://forums.pmmp.io) for support.
Thanks, but this issue tracker not intended for support requests. Please read the guidelines on [submitting an issue](https://github.com/pmmp/PocketMine-MP/blob/master/CONTRIBUTING.md#creating-an-issue).
[Docs](https://pmmp.rtfd.io) | [Discord](https://discord.gg/bge7dYQ) | [Forums](https://forums.pmmp.io)
# Whether to close issues marked as support requests
close: true
# Whether to lock issues marked as support requests

1
.gitignore vendored
View File

@ -12,6 +12,7 @@ server.properties
/pocketmine.yml
memory_dumps/*
resource_packs/
server.lock
# Common IDEs
.idea/

2
.gitmodules vendored
View File

@ -2,7 +2,7 @@
path = src/pocketmine/lang/locale
url = https://github.com/pmmp/PocketMine-Language.git
[submodule "tests/preprocessor"]
path = tests/preprocessor
path = build/preprocessor
url = https://github.com/pmmp/preprocessor.git
[submodule "tests/plugins/PocketMine-DevTools"]
path = tests/plugins/PocketMine-DevTools

View File

@ -1,45 +1,32 @@
# [![PocketMine-MP](http://cdn.pocketmine.net/img/PocketMine-MP-h.png)](https://pmmp.io)
__A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP__
<p align="center">
<a href="https://pmmp.io"><img src="http://cdn.pocketmine.net/img/PocketMine-MP-h.png"></img></a><br>
<b>A highly customisable, open source server software for Minecraft: Bedrock Edition written in PHP</b>
</p>
[![Build Status](https://travis-ci.org/pmmp/PocketMine-MP.svg?branch=master)](https://travis-ci.org/pmmp/PocketMine-MP)
### Setup, help & support, FAQs
Head over to the [documentation site](http://pmmp.readthedocs.org/).
If you don't find what you're looking for there, [talk to a human](#discussion). Please do not use our issue tracker for support requests.
### Getting started
- [Documentation](http://pmmp.readthedocs.org/)
- [Installation instructions](https://pmmp.readthedocs.io/en/rtfd/installation.html)
- [Docker image](https://hub.docker.com/r/pmmp/pocketmine-mp)
- [Plugin repository](https://poggit.pmmp.io/plugins)
### Discussion
- [Forums](https://forums.pmmp.io/)
### 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.
- [Community Discord](https://discord.gg/bge7dYQ)
### For developers
* [Latest API documentation](https://jenkins.pmmp.io/job/PocketMine-MP-doc/doxygen/) - Doxygen documentation generated from development
* [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - A development tools plugin for creating plugins.
* [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - Development tools plugin for creating plugins
* [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
* [Contributing Guidelines](CONTRIBUTING.md)
### Can I contribute?
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?
- 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.
### Donate
- Bitcoin Cash (BCH): `qq3r46hn6ljnhnqnfwxt5pg3g447eq9jhvw5ddfear`
- Bitcoin (BTC): `171u8K9e4FtU6j3e5sqNoxKUgEw9qWQdRV`
- [Patreon](https://www.patreon.com/pocketminemp)
## Licensing information
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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
This project is licensed under LGPL-3.0. Please see the [LICENSE](/LICENSE) file for details.
pmmp/PocketMine are not affiliated with Mojang. All brands and trademarks belong to their respective owners. PocketMine-MP is not a Mojang-approved software, nor is it associated with Mojang.

81
build/make-release.php Normal file
View File

@ -0,0 +1,81 @@
<?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\build_script;
use pocketmine\utils\VersionString;
use function dirname;
use function fgets;
use function file_get_contents;
use function file_put_contents;
use function preg_quote;
use function preg_replace;
use function sleep;
use function sprintf;
use function system;
use const pocketmine\BASE_VERSION;
use const STDIN;
require_once dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
require_once dirname(__DIR__) . '/vendor/autoload.php';
if(isset($argv[1])){
$currentVer = new VersionString($argv[1]);
}else{
$currentVer = new VersionString(BASE_VERSION);
}
$nextVer = new VersionString(sprintf(
"%u.%u.%u",
$currentVer->getMajor(),
$currentVer->getMinor(),
$currentVer->getPatch() + 1
));
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev) : void{
$versionInfo = file_get_contents($versionInfoPath);
$versionInfo = preg_replace(
$pattern = '/^const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
'const BASE_VERSION = "' . $newVersion . '";',
$versionInfo
);
$versionInfo = preg_replace(
'/^const IS_DEVELOPMENT_BUILD = (?:true|false);$/m',
'const IS_DEVELOPMENT_BUILD = ' . ($isDev ? 'true' : 'false'). ';',
$versionInfo
);
file_put_contents($versionInfoPath, $versionInfo);
}
$versionInfoPath = dirname(__DIR__) . '/src/pocketmine/VersionInfo.php';
replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false);
echo "please add appropriate notes to the changelog and press enter...";
fgets(STDIN);
system('git add "' . dirname(__DIR__) . '/changelogs"');
system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"');
system('git tag ' . $currentVer->getBaseVersion());
replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true);
system('git add "' . $versionInfoPath . '"');
system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"');
echo "pushing changes in 10 seconds\n";
sleep(10);
system('git push origin HEAD ' . $currentVer->getBaseVersion());

1
build/preprocessor Submodule

Submodule build/preprocessor added at b01f50c50e

182
changelogs/1.3.md Normal file
View File

@ -0,0 +1,182 @@
# 1.3.3
- Minecraft: Pocket Edition alpha 0.7.2 compatible!
- Unicode support
- Fixed /difficulty command
- Fixed a few flying kicks
- Fixed async. operations thread
- Added whitelist enabled property to Query
# 1.3.4
**This is a compatibility update for Minecraft: Pocket Edition v0.7.3 alpha.**
Double chests do not work yet, we will fix more bugs and add them when MCPE 0.7.4 is released. There were too many bugs in 0.7.3 to test double chests properly.
#### Including in this release:
- Fixed armor crash
- Fixed ghost armor
- Fixed packets being received after player disconnection
- Fixed player count bug
- Added compatibility with encrypted login
- Fixed flying check on fences
- Fixed players connecting with empty usernames
- Fixed several crashes related to Items
- Added temporal water flowing. Really buggy
- Automatic recovery of index-corrupted maps
- Fixed hotbar reset when changing armor
- Fixed some hotbar reset bugs on block placement
- Added basic tool durability and breaking
- Chests now have opening/closing animation.
- Fixed /difficulty
- In-game player list is now handled correctly
- Player entities are saved in all worlds to remove join/leave spam
- Quartz slabs
# 1.3.5
#### Including in this release:
- Fixed block durability (blocks being replaced)
- Added armor replacing (changing the armor while you have other)
- Added proper Player object cleanups as a fix to a memory leak
# 1.3.7
**This update is compatible with Minecraft: Pocket Edition v0.7.4 alpha.** Older versions won't work.
In Minecraft: PE 0.7.4 you can add External servers directly. [How to add servers](https://github.com/PocketMine/PocketMine-MP/wiki/How-to-add-servers)
![](http://i.imgur.com/ltBJgmUl.png)
### Changelog
- **Updated for 0.7.4 alpha**
- **New API version 10**
- Adds Tile methods
- Changes message events to use new Minecraft protocol
- Added Level::getSafeSpawn()
- Linux now uses PHP 5.5.3
- Removed water updating
- Fixes for Player teleporting
- Removed invalid Cookie and fish items
- Fixed Stone brick and quartz slab recipes
- Shears now are used to drop leaves
- Fixed a crash on Windows XP
- Cake is removed when the bottom block is broken
- Added new NBT parser/writer
- Fixed chests and furnaces drops when broken.
- Fixed signs not spawning on world load
- Fixed actions not being deleted (memory leak)
- Chests now are spawned correctly
- Double chests
- Added random x,z offset to item drops
# 1.3.8
This release consists of a few bugfixes and several features added. It is compatible with MCPE 0.7.4 and 0.7.5
**Changelog:**
- No API changes
- Fixed x,y,z indexes when opening a Furnace
- Fixed invalid fix for CPU usage limiter on idle
- Fixed cross-compiling
- Fixed some Stonecutter recipes
- Fixed a few items stack sizes
- Fixed TimeAPI bugs
- Forces position on teleport, blocks fast teleport mods
- Fixed some blocks havin a send lag on place/break
- Fixed Sign Posts not deleting the Tile data when broken by update
- Fixed Ice converting to Water on creative mode
- Added beds
- Added scheduled teleport on spawn to fix spawning underground
- Added date to console logs
# 1.3.9
This release is compatible with MCPE 0.7.4 and 0.7.5.
**Changelog:**
- Fixed server crash related to beds
- Player movement is less laggy
- Added new text formatting system for future updates
- New Terminal Emulator for Windows
- More colors! Less warnings!
# 1.3.10
**Changelog:**
- Added door sounds
- Fixed bed sleeping position offset
- Added explosions
- Flint & Steel on Creative Mode (replaces Eggs)
- Changed the Sword and Hoe to the diamond tier on the Creative inventory
- Fixed colors on MacOS
- Water flow
- Fixed Windows console input not being accepted when using special keys
- Added a way to disable console colors
- Updated PHP to 5.5.6, pthreads to 0.0.55, and cURL
- Armor drops
- Fixed plugin issues
- Fixed some block drops
- Fixed a crash when @all is used in console, and only usable for OPs
- Fixed some issues regarding teleporting
- deop no longer op the player again
# 1.3.11
And here it comes the stable release for **MCPE v0.8.1 alpha**. We decided to remove the improved networking that was delaying this release, but you should see it in the next one. Minecarts couldn't be added for the same reason as mobs, but we will try to implement "fake" minecarts that behave correctly inside rails, but not outside of them.
Starting with this release, all PocketMine-MP versions will be given a codename. This one received the codename 「甘いビートルート」_(Amai Beetroot)_.
**Changelog:**
- Fixed existing Packets of Death
- Fixed lots of bugs related to crafting
- Fixed block placement bugs
- Redstone ore drops redstone dust
- Sideway logs
- Sponges
- Added new wooden planks & stairs
- Added iron bars, cobblestone walls and pumpkins
- Added carpets, hay bales and coal blocks
- Added potatoes, carrots and beetroots
- Additional tall grass drops
- Achievements
- Added multiple orders for _/gamemode_ command
- Chat plugins can work with each other #975
- Fixed internal world chunks bug
- Private messages are now hidden on console except when the console is the target/origin
- PHP plugins are now loaded with include()
- Fixed plugin paths
- Added source SHA1 sum to crash reports
- Added Level::startTime() and Level::stopTime()
- Fixed server not being able to start on several OS when offline
- More small fixes and small additions
For more information, check the [complete changelog](https://github.com/PocketMine/PocketMine-MP/compare/Alpha_1.3.10...Alpha_1.3.11).
# 1.3.12
Before starting to rewrite even more parts of the code, we are releasing the last version of the Alpha_1.3.x Amai Beetroot「甘いビートルート」. Next one will be Alpha_1.4 with more rewrite!
We have included the new Event API that will be used on the next release, but now it is only used to hook on packets.
**API Changelog:**
- **Full network rewrite.** Plugins can work with packets easily now.
- **New Event API,** only implemented for packets right now.
- Added player.block.place.bypass and player.block.break.bypass
- Level included in data for event item.drop
- Added Utils::getUniqueID()
- **Added default support in PHP binaries for MySQLi**
- Removed Spyc
- Call Plugin::__destruct() on PluginAPI::__destruct()
- Added more OS detection on Utils::getOS()
**Changelog:**
- New set-up wizard in multiple languages. Help translate it to more languages on http://translate.pocketmine.net/
- Updated pthreads and PHP binaries
- New font for MinTTY console on Windows
- Send partial hotbar history
- Fixed Tile saving indexes
- Fixed a few teleport bugs
- Improved crash dumps
- Increased apple health restore
- Fixed players being invincible after death
- Fixed Level::unloadChunk() not using saveEnabled
- Show player name on bad username kick
- Fixed item duplication on void #1100
- OPs can bypass the player limit
- Fixed item replacing on furnace #1114
- Fixed multiple small bugs #1058 #1032 #854 #823 #1135 #1150 #1172 #1173 #486 #466 #483
- Fixed PHP compilation on 64-bit linux #519 #861 #940 #505 #590 #761 #129
- Included OPCache to optimize opcodes
If you are on Linux, you can use `wget -q -O - http://cdn.pocketmine.net/installer.sh | bash -s - -v Alpha_1.3.12` to update. If you are on a MacOS, use `curl -sL http://cdn.pocketmine.net/installer.sh | bash -s - -v Alpha_1.3.12`

1278
changelogs/1.4.md Normal file

File diff suppressed because it is too large Load Diff

72
changelogs/1.6.md Normal file
View File

@ -0,0 +1,72 @@
# 1.6.1dev-87
**For Minecraft PE 0.16.0.5 alpha**
**THIS IS A PRE RELEASE. Do not use it in production unless you are sure you know what you are doing.**
Only changes since the 1.6dev tag will be documented here. Changes between 1.4.1 and 1.6dev are far too extensive to document effectively.
## Core
- New RNG, based on XorShift128 from the php-random library. This fixes issue with repeating terrain on 32-bit systems. _Note however that new generation into existing worlds will not be seamless._
- Block and Item IDs have been moved to interfaces for better consistency
- Better method for synchronisation of client/server time (less packet spam)
- Utils::getRandomBytes() has been deprecated in favour of php7's random_bytes() function.
- `<player>.dat` saving/reading can now be disabled in `pocketmine.yml` (set `player.save-player-data` to `false`)
## Gameplay/game features
- Added Flower Pots
- Containers can now be opened in creative
- Trapdoors can now be placed without a supporting block
## API
This release has API changes, bumping the version to 2.1.0.
### Entity metadata (0.16)
Many changes have been made to entity metadata. Many true/false data properties are now entity status flags, such as NoAI, NametagVisible and various others. Entity status flags can be set using:
`$entity->setDataFlag(Entity::DATA_FLAGS, Entity::INSERT_DATA_FLAG_NAME, true/false);`
**Breaking** changes are detailed here. Additions are not documented. https://gist.github.com/dktapps/76b291b7a861762b54f7a8b834389883
**NOTE: It's strongly recommended to use provided API methods where possible instead of tampering with metadata directly.**
### AsyncTask API additions
- Main thread local storage: Developers can pass any data including objects to the constructor of AsyncTask such that the data can be retrieved after the AsyncTask completes using the new `AsyncTask::fetchLocal()` method, or use the `AsyncTask::peekLocal()` method to get the data without removing it.
- Progress updates: Developers can use the new `AsyncTask::publishProgress() method and override`AsyncTask::onProgressUpdated()` to handle AsyncTask progress information in the main thread.
Refer to #1 and #100 for details.
### WeakPosition
WeakPosition was added in 1.6.1 to fix bugs with unloading levels which have player spawn points set in them. This type of position holds a level ID instead of a direct reference. Use this when your position may outlive the level it is in.
### Removal of Item/NBT circular dependency
Refer to #121 for details.
### Other
- Added Player->sendWhisper() (#73).
- Removed LargeExplodeParticle due to incorrect name - use HugeExplodeParticle. Added HugeExplodeSeedParticle and BlockForceFieldParticle (7314aaf7f7bdae582f674c085c7ae879985bf847)
## Fixes
- Fixed the infamous hotbar spaz bug
- Creative/spectator inventory now sends correctly
- Fixed spectator flight controls
- Fixed issues with items going past the end of the regular inventory
- Fixed furnace client crashes
- Fixed inventory windows for anvils and enchanting tables
- Fixed kicked for walking on lily pads (#blameshoghicp)
- Fixed a nasty entity-related memory leak on chunk unload
- Fixed sleeping players floating above beds and teleportation of sleeping players.
- Fixed a bug in Level::updateAround() where only one block would update
- Fixed some slab placement issues (#31)
- Fixed crash loading 1.11 worlds (#32)
- Fixed broken `--disable-readline` command-line option (#34)
- Fixed world unload crash when players have spawnpoints set in that world (#24)
- Fixed start.sh detection of system PHP binaries (#66)
- Fixed anvil rotation when placed and variant drops (d696049a0ad5e3b878a8f902e4ef75f19ec8cecc)
- /timings command is now more verbose about paste errors (#95)
- Fixed server crash at shutdown when RCON is enabled (#101)
- Fixed server name is always "Minecraft: PE Server" when running setup wizard (92bd1a755d4b171b687538db83893b9bd9c70420)
- Fixed CraftItemEvent->getInput() does not return used items (7eb9530346e953d1555623ff871086f85447b6c6)
- Fixed useless ServerKiller (#122)

1155
changelogs/3.0-alpha.md Normal file

File diff suppressed because it is too large Load Diff

264
changelogs/3.0.md Normal file
View File

@ -0,0 +1,264 @@
**For Minecraft: Bedrock Edition 1.4.0**
Plugin scheduler rewrite, RCON rewrite, performance improvements, improved idle memory usage
**While this release is nominally not an alpha, it is still not feature complete and does not include all gameplay features. Please do not create issues for missing gameplay features.**
This build has breaking API changes.
This release is the first to use the new merged versioning system. The PocketMine-MP version and the API version are now one and the same.
Please use our issue tracker to report bugs.
# 3.0.0
## Core
### General
- This release introduces a new dependency library called `Snooze`, which PocketMine-MP utilizes for managing notifications between threads. This library is currently utilized by command reading, RCON and RakLib, allowing faster response times to commands, reduced network latency, and better performance due to lack of need for polling.
- Fixed race condition causing `ServerKiller` to sometimes kill the server for no reason on shutdown.
### Dependency libraries
Requires the following libraries:
- [`pocketmine/raklib` `^0.12.0`](https://github.com/pmmp/RakLib/releases/0.12.0)
- [`pocketmine/spl` `^0.3.0`](https://github.com/pmmp/SPL/releases/0.3.0)
- [`pocketmine/binaryutils` `^0.1.0`](https://github.com/pmmp/BinaryUtils/releases/0.1.0)
- [`pocketmine/nbt` `^0.2.0`](https://github.com/pmmp/NBT/releases/0.2.0)
- [`pocketmine/math` `^0.2.0`](https://github.com/pmmp/Math/releases/0.2.0)
- [`pocketmine/snooze` `^0.1.0`](https://github.com/pmmp/Snooze/releases/0.1.0)
These libraries may individually have changes which are not recorded here. See their independent repository releases for their changelogs.
### Async pooling
- Async workers are now started dynamically when they are needed only, instead of being started immediately on startup. This allows reducing idle memory usage.
- AsyncPool now appropriately shuts down the workers when instructed to, instead of leaving it up to the ThreadManager to clean it up. This eliminates debug messages of shutting down async workers on server shutdown.
- Default maximum async worker memory limit has been lowered from 1024MB to 256MB.
- Async workers are now started using the options `PTHREADS_INHERIT_CONSTANTS | PTHREADS_INHERIT_INI`, which reduces idle memory wastage and works around some bugs in pthreads.
### Entities
- Fixed entities not being despawned when flagged, if they weren't scheduled for an update.
### Levels
- Seed handling is now always consistent between `pocketmine.yml` and `server.properties`.
- Fixed generation bugs in imported LevelDB worlds where the classpath was saved into level.dat.
- Generators for levels are no longer created on the main thread, reducing memory usage.
### Plugins
- Plugin data is now stored under `<data dir>/plugin_data` by default on new installations, instead of in `<plugins dir>`. This behaviour does not affect existing installations by default - if you want to enable it, set `plugins.legacy-data-dir` to `false` in `pocketmine.yml`.
### RCON
RCON has been almost completely rewritten in this release.
- Now event-driven (using Snooze) instead of poll-based, improving performance.
- Fixed segmentation fault when stopping the server with RCON enabled.
## API
**WARNING: Dependency library API changes are not listed here. See their individual release notes for changes (linked above in the Core section).**
### API versioning changes for plugins
The way that the API versioning is done has changed. Now the API version is synonymous with the PocketMine-MP version.
Plugin compatibility is determined by the following:
- Take the base version, and strip any metadata (everything after the `+` sign, for example `3.0.0+dev.1191` becomes `3.0.0`).
- Assert that:
- The major versions is the same
- The server's minor version is greater than or equal to the plugin's
- The server's patch version is greater than or equal to the plugin's
Currently there is no support for locking version by metadata, although this could be implemented if it is a wanted feature.
### General
- `Server->getCodename()` and `\pocketmine\CODENAME` have been removed.
- Added API method `Server->getTickSleeper()`, which returns a `\pocketmine\snooze\SleeperHandler` instance.
- `Server->getIp()` now returns `0.0.0.0` if not set.
### Block
- Added `Block->getXpDropForTool()`.
### Entity
- Calling `scheduleUpdate()` on an `Entity` after it has been `close()`d will now cause an exception to be thrown.
- `Entity->motionX`, `Entity->motionY` `Entity->motionZ` have been removed in favour of an `Entity->motion` `Vector3` field. This also applies for the `lastMotion` fields.
- `Entity->isInsideOfWater()` has been renamed to `isUnderwater()`.
### Events
- Added support for `@softDepend` annotation on event handlers, which allows the event handler to not be registered if the dependency plugin is not loaded.
- Added support for `@notHandler` annotation for `Listener` methods to indicate that such methods are not event handlers.
- Typehints have been applied to the events API to PHP 7.2 standards.
- Fixed preventing effect expiry using `EntityEffectRemoveEvent` not being reflected on the client.
- `EntityDamageEvent` API has significant changes. The general purpose of this is to split up base damage from modifiers.
- Added methods `getBaseDamage()`, `setBaseDamage()`, `getOriginalBaseDamage()`, `getModifiers()`, `getOriginalModifiers()`
- `setDamage()` renamed to `setModifier()`, and type parameter is now mandatory
- `getDamage()` renamed to `getModifier()`, and type parameter is now mandatory
- `getOriginalDamage()` renamed to `getOriginalModifier()`, and type parameter is now mandatory
- Removed `MODIFIER_BASE` constant
- Constructors now accept: `float baseDamage`, `float[] modifiers` instead of just `float[] modifiers`
- Added `BlockBreakEvent->getXpDropAmount()` and `BlockBreakEvent->setXpDropAmount()`.
### Inventory
- `InventoryTransaction->getCreationTime()` has been removed.
- `EntityInventoryChangeEvent` and `EntityArmorChangeEvent` are no longer fired during entity inventory intialization.
### Item
- Methods `isPickaxe()`, `isAxe()`, `isSword()`, `isShovel()`, `isHoe()`, `isShears()` have been removed. These should be replaced with `instanceof` checks for the relevant classes.
- Removed `Item->useOn()`. This has been superseded by new methods used for handling durability changes.
- Added hooks `Item->onDestroyBlock()` and `Item->onAttackEntity()`. These are called when a player uses the item to destroy a block or attack an entity respectively. This is used in the core code for updating durability.
- `Item->pop()` now accepts an optional count parameter.
- `Enchantment` now has separated primary items (which can be enchanted directly) and secondary items (which can be enchanted on an anvil). The constructor of `Enchantment` has been updated to reflect this.
- Removed `Enchantment->getSlot()` and `Enchantment->hasSlot()`.
- Added `Enchantment->getPrimaryItemFlags()`, `Enchantment->hasPrimaryItemFlag()`, `Enchantment->getSecondaryItemFlags()` and `Enchantment->hasSecondaryItemFlag()`
### Level
- `Biome` classes have been moved to `pocketmine\level\biome` namespace. This is in preparation for future work on Levels which requires biome information (such as weather conditions).
- `WeakPosition` has been removed.
- Added `Level->getBiome()`.
- `Level->getSafeSpawn()` now always returns a `Position` instance.
- `Level->getBlockExtraData()` and `Level->setBlockExtraData()` have been removed (as well as their associated `Chunk` methods).
- `ChunkManager->isInWorld()` now accepts integers instead of floats.
- Added `SubChunkIteratorManager->invalidate()`.
#### Generator
- `BiomeSelector` has been refactored to make it simpler and more robust.
- Generator-management methods `registerDefaultGenerators()`, `addGenerator()`, `getGeneratorList()`, `getGenerator()`, and `getGeneratorName()` have been moved from `Generator` to a new `GeneratorManager` class.
- Static noise functions in the `Generator` base class have been moved to `Noise` instance methods.
- Added static method `Generator::convertSeed()`, which converts an int or string into a numeric seed for generation.
### Network
- `SourceInterface->process()` no longer returns a value.
### Plugin
- `PluginBase->getResources()` now returns an associative array where the index is the path to the resource relative to the plugin's `resources` directory.
- `PluginLoader`s have been almost completely rewritten to make them simpler and more robust.
- `PluginManager->registerInterface()` does not return anything, and now accepts a `PluginLoader` instance instead of a `string`.
- `PluginLoader`:
- `getPluginFilters()`, `enablePlugin()` and `disablePlugin()` are removed.
- `loadPlugin()` responsibilities are now solely confined to doing whatever is necessary to make the plugin's classes visible by the server, and does not emit log messages or check for data directories.
- Added method `getAccessProtocol()` which determines what prefix to apply to the plugin path to access the files inside it (for example `phar://`).
- `PluginBase->init()` and `PluginBase->isInitialized()` have been removed.
- `Plugin` interface now declares a signature for the constructor which implementations must comply with.
- `Plugin` interface now declares `setEnabled()`.
- It is now possible to create a custom `Plugin` implementation without requiring a custom `PluginLoader`.
### Scheduler
This release features major changes to how plugin task scheduling works.
- Removed `Server->getScheduler()`. All plugins now have their own scheduler which is accessible using `Plugin->getScheduler()`. Aside from being syntactically more concise and pleasant, this also allows much more effective management of tasks when plugins are disabled.
- Removed `PluginTask` class, because it's now unnecessary. Previously it was required to allow the server to delete tasks associated with a plugin when the plugin was disabled. With plugin-owned schedulers, this is no longer a requirement. Plugins may now utilize the `Task` class as a base if they like.
- Added `Server->getAsyncPool()`. Since the global scheduler does not exist any more, it does not manage the server's `AsyncPool` any more. Additionally, `ServerScheduler` was previously bloated by a lot of `AsyncTask` related methods, which are now not necessary because direct access to `AsyncPool` is granted instead.
- `ServerScheduler`:
- `ServerScheduler` has been renamed to `TaskScheduler` since it is now a general-purpose task scheduler which is non-dependent on the user. This allows much greater flexibility and also makes it possible to unit-test.
- All `AsyncTask`/`AsyncPool` related methods have been removed - the task scheduler does not manage the async pool anymore.
- Calls to `Server->getScheduler()->scheduleAsyncTask()` should be replaced with `Server->getAsyncPool()->submitTask()`.
- Calls to `Server->getScheduler()->scheduleAsyncTaskToWorker()` should be replaced with and `Server->getAsyncPool()->submitTaskToWorker()`.
### Tile
- Calling `scheduleUpdate()` on a `Tile` after it has been `close()`d will now cause an exception to be thrown.
- Tile NBT is now ephemeral and is not retained after creating the tile.
- `Tile->namedtag` has been removed.
- `Tile->saveNBT()` now returns a new `CompoundTag` containing saved data.
- Added new protected methods `Tile->readSaveData()` and `Tile->writeSaveData()`. These should be overridden to add or read tile-specific data, instead of overriding `saveNBT()` and `__construct()`.
### Utils
- Added `MainLogger->getFormat()` and `MainLogger->setFormat()` to allow manipulating console output format.
## Gameplay
### General
- Fixed a range of block collision issues stemming from off-by-one errors when fetching areas.
### Blocks
- Fixed a crash which occurred when leaving a bed which was broken and replaced during sleep.
- Fixed dark oak and acacia saplings growing into oak trees - now they will not grow at all (they need to be implemented).
- Saplings now take light level into account when trying to grow.
- Ores and other blocks now drop experience when broken with an appropriate tool.
### Entities
- Fixed dropped items not being correctly destroyed by fire, cacti and other damage sources.
### Generation
- Grass no longer generates as the top layer of ground cover in river biomes.
- Ocean biomes now use gravel instead of grass+dirt for ground cover.
- Reduced maximum elevation of plains biomes to make them less bumpy.
- Snow layers and other can-be-flowed-into blocks no longer generate underwater.
### Items
- Buckets are no longer able to delete any block by replacing it with water.
- Dried Kelp, Bleach, Nautilus Shell and Heart of the Sea items are registered (although crafting recipes for these are not yet available).
- Implemented `Vanishing` enchantment.
- Implemented Totems.
### World
- Fixed explosions sometimes leaving behind air blocks with non-zero damage values.
# 3.0.1
- Fixed error when players move things around in the crafting grid after plugins cancel `PlayerInteractEvent` on crafting tables.
# 3.0.2
- Fixed memory dumps not showing private properties of parent classes.
- Fixed a memory leak when cancelling all tasks in the `TaskScheduler`.
- Fixed scheduled task timings showing `Unknown` as the plugin name.
# 3.0.3
- Fixed possible crash in Sign when placed by a plugin.
- Fixed slightly-damaged and very-damaged anvils dropping incorrect items.
- `Living->applyPostDamageEffects()` is no longer called if the mob died from an attack.
- Cooldown for mob attack is now reset prior to applying post-damage effects.
- Added constant `ItemIds::MUTTON` to resolve crashes using PC worlds.
- Fixed emerald ore not dropping XP when broken with a valid tool.
- Fixed mobs getting crazy vertical knockback if attacked while airborne.
- Fixed XP orbs continuing to follow dead players.
# 3.0.4
- Fixed RCON spamming the console when a client does not disconnect correctly.
- Fixed dropping chunk cache unnecessarily when no blocks need to be updated on a chunk.
- Fixed outdated block updates getting sent on chunks replaced using `setBlock()`.
# 3.0.5
- Fixed not being able to place blocks where a player died and has not yet respawned (#2265).
- Fixed mob death animation not being played when `Entity->kill()` is called directly or `/kill` is used.
- Fixed viewers of different halves of double chests not seeing changes made by viewers who opened the other half (#2261).
- Fixed bugs setting items into wrong indexes when double chest halves have differently sized inventories.
- Fixed `getConfig()` crashing when called when the plugin's data directory doesn't exist.
- Fixed a possible exploit with keychain signing for XBL login.
# 3.0.6
- Fixed invalid keys in `.properties` config files being considered as invalid strings.
- Fixed whitespace between key and value `key = value` being invalid in `.properties` config files.
- Fixed a bug in exception message when an invalid permission type is written for a command in plugin.yml.
- Properly fixed newline issues when parsing event handler annotations - `@notHandler` will now work as expected when CRLF line endings are used.
- Fixed `PluginManager->registerEvents()` registering functions as event handlers declared by parent classes which are not `Listener` instances (#2293).
# 3.0.7
- Fixed setting spawn points in un-generated chunks causing the player to fall out of the world.
- Fixed spawn protection deactivating when there are no ops set (this was an unwanted/unexpected feature, so it's considered a bug).
- Fixed cursor items not getting dropped when closing the inventory or dying.
- Fixed more issues with blocks with invalid metadata appearing as update! blocks.
- `Entity->setNameTagAlwaysVisible()` now works (although nametags will still not be shown if the entity is invisible, due to a behavioural change in Minecraft PE).
- Fixed errors passing zero motions to projectiles in some cases.
# 3.0.8
- Fixed player on-ground state not updating when moving horizontally. This allowed fly hacks with the built in anti-cheat, and also affected some third party anti-cheat plugins due to the effect on `inAirTicks`.
- Fixed knockback. PC 1.9-style knockback was mistakenly introduced in 3.0.3. This has now been reverted back to the old 1.8-style behaviour.
# 3.0.9
- Cleaned up odd behaviour of `/kill` due to old broken code.
- Fixed patch level check for plugin APIs not allowing lesser patch versions on greater minor versions.
- Fixed `/timings paste`. This now reports directly to the timings host instead of using Ubuntu Pastebin.
- Minor code cleanups in various places.
- Zip resource packs will now give slightly less useless errors - errors for broken manifest have been separated from those with fields missing, and now reports why decoding failed if it failed.
# 3.0.10
- Syntax error crashdumps will no longer be reported to the crash archive.
- Chunk sending is now fault-tolerant. Before this release, any error on a worker during async chunk sending (such as memory errors caused by pthreads) would cause that chunk to never get sent, resulting in invisible and missing chunks. Levels will now attempt to retry chunk prepare when a task crashes, which should fix most invisible chunk bugs.
- `MainLogger` now logs exception stack traces in a synchronized block to ensure that they are coherent when log messages are emitted from multiple threads at once.
- `AsyncTask->isCrashed()` now returns `true` if a fatal error occurred during the task execution.
# 3.0.11
- `DropItemAction` will now consider itself invalid if attempting to drop a null item.
- Fixed leaking globally broadcasted Level packets when no players are on the server.
- Fixed title bar not being cleared on server stop on some terminals.
- Fixed `FallingBlock` saving corrupted data.
- Fixed the structure of `GuiDataPickItemPacket`.
- Cleaned up some code in `OfflinePlayer`.
- Splash potions no longer apply effects to dead (but not yet respawned) players.
- Coal ore no longer drops XP when mined with a silk touch tool.
- Item entities now cannot be picked up when a negative pickup delay is used.
# 3.0.12
- `Config` keys which are considered bools by YAML 1.1 will no longer be transformed into 1 or 0.
- Fixed painting motives not getting saved.
- Fixed cacti spewing items when placed in some invalid locations.
- Fixed entity fire damage not applying in the void.
- Fixed entities not getting updated appropriately in some conditions.

68
changelogs/3.1.md Normal file
View File

@ -0,0 +1,68 @@
**For Minecraft: Bedrock Edition 1.5.0**
### Note
Plugins compatible with any previous 3.x.y version will also run on this build and do not need API bumps. Plugin developers should **only** update their required API to this version if you need the changes in this build.
**This build contains changes to the **protocol** which are not covered by the API version. To lock your plugin to a specific protocol version, declare the `mcpe-protocol` attribute in your `plugin.yml`.
# 3.1.0
- Support for Minecraft: Bedrock Edition version 1.5.0
# 3.1.1
- Fixed player on-ground state not updating when moving horizontally. This allowed fly hacks with the built in anti-cheat, and also affected some third party anti-cheat plugins due to the effect on `inAirTicks`.
- Fixed knockback. PC 1.9-style knockback was mistakenly introduced in 3.0.3. This has now been reverted back to the old 1.8-style behaviour.
# 3.1.2
- Cleaned up odd behaviour of `/kill` due to old broken code.
- Fixed patch level check for plugin APIs not allowing lesser patch versions on greater minor versions.
- Fixed `/timings paste`. This now reports directly to the timings host instead of using Ubuntu Pastebin.
- Minor code cleanups in various places.
- Zip resource packs will now give slightly less useless errors - errors for broken manifest have been separated from those with fields missing, and now reports why decoding failed if it failed.
- Added constant `Entity::DATA_FLAG_SHOW_TRIDENT_ROPE`.
# 3.1.3
- Syntax error crashdumps will no longer be reported to the crash archive.
- Chunk sending is now fault-tolerant. Before this release, any error on a worker during async chunk sending (such as memory errors caused by pthreads) would cause that chunk to never get sent, resulting in invisible and missing chunks. Levels will now attempt to retry chunk prepare when a task crashes, which should fix most invisible chunk bugs.
- `MainLogger` now logs exception stack traces in a synchronized block to ensure that they are coherent when log messages are emitted from multiple threads at once.
- `AsyncTask->isCrashed()` now returns `true` if a fatal error occurred during the task execution.
# 3.1.4
- `DropItemAction` will now consider itself invalid if attempting to drop a null item.
- Fixed leaking globally broadcasted Level packets when no players are on the server.
- Fixed title bar not being cleared on server stop on some terminals.
- Fixed `FallingBlock` saving corrupted data.
- Fixed the structure of `GuiDataPickItemPacket`.
- Cleaned up some code in `OfflinePlayer`.
- Splash potions no longer apply effects to dead (but not yet respawned) players.
- Coal ore no longer drops XP when mined with a silk touch tool.
- Item entities now cannot be picked up when a negative pickup delay is used.
- Fixed extra byte at the end of `PlayerSkinPacket` not being read (1.5 protocol change that somehow got lost).
# 3.1.5
- `Config` keys which are considered bools by YAML 1.1 will no longer be transformed into 1 or 0.
- Fixed painting motives not getting saved.
- Fixed cacti spewing items when placed in some invalid locations.
- Fixed entity fire damage not applying in the void.
- Fixed entities not getting updated appropriately in some conditions.
# 3.1.6
- Fixed players disconnected during login verification getting leaked and not destroyed correctly.
- Updated NBT dependency to 0.2.1 to receive bug fixes (see https://github.com/pmmp/NBT/releases/tag/0.2.1).
# 3.1.7
- Errors thrown during level tick will now crash the server instead of spamming the console.
- Fixed arrows despawning too soon after hitting the ground.
- Fixed projectiles despawning before colliding if they were airborne for > 60 seconds.
# 3.1.8
- Fixed levels unloaded during an earlier level's tick on the same tick causing a crash.
- PermissibleBase->clearPermissions() now properly unsubscribes from all permissions.
- Fixed incorrect break check for standing torch.
- Fixed drops for brewing stand.
- Fixed block picking brewing stand, bed, double slab, cake, farmland, and mob heads giving the wrong items.
- Fixed blocks not placing correctly when clicking on redstone ore.
- Fixed unknown PC items in tile inventories crashing the server - now they'll be quietly removed instead.
- Fixed server freezing when eating chorus fruit from high altitude.
- `readline` is now disabled by default on Windows and must be explicitly enabled with `--enable-readline` due to thread-safety issues.
- Fixed server crash when trying to use non-implemented splash potions.
- Removed incorrect maximum region file size cap which may have caused some worlds to be incorrectly detected as corrupted.

121
changelogs/3.2.md Normal file
View File

@ -0,0 +1,121 @@
**For Minecraft: Bedrock Edition 1.6.0**
This is a minor feature release, including support for Minecraft Bedrock 1.6.0, some new minor gameplay features and some API deprecations and additions.
### Note
Plugins compatible with any previous 3.x.y version will also run on this build and do not need API bumps.
However, some API features have been deprecated in this version. Plugin developers do not need to do anything about these deprecations immediately, however they may raise harmless warnings if used.
Features marked **`@deprecated`** are **recommended** not to be used, but will continue to work for any future 3.x.y versions. They will be removed in the next major release (4.0).
# 3.2.0
### Core
- `Level` generators are now registered only when needed instead of as soon as a worker starts. This drastically reduces memory consumption on servers with lots of workers.
- Async workers are now garbage-collected along with everything else on the default schedule. Idle workers with 0 queued tasks will be shutdown and removed from the pool to reduce memory usage.
- UPnP error messages are now more informative of troubleshooting steps.
- Errors are no longer caught in cases where they are unrecoverable.
### API
#### Entity
- Arrow pickup mode can now be controlled via `Arrow->setPickupMode()`. This accepts one of three `Arrow` constants: `PICKUP_NONE`, `PICKUP_ANY`, `PICKUP_CREATIVE`.
- Added new API methods `Projectile->getBaseDamage()` and `Projectile->setBaseDamage()`.
- Added new API methods `Entity->getScoreTag()` and `Entity->setScoreTag()`.
#### Events
- The `Listener` interface has now received in-depth documentation about its behaviour and uses. See the top of the `Listener` class to read it.
- It is now possible to declare `@ignoreCancelled` on an event handler without specifying `true` or `false`. If no value is found, `true` will be assumed.
- `ServerCommandEvent` and `RemoteServerCommandEvent` are now **`@deprecated`** and their usage discouraged. A new generic `CommandEvent` has been introduced in its place, which allows capturing commands from any type of command sender. This was done in response to difficulties of code duplication when wanting to intercept commands from both console and players.
- `EntityDamageEvent`
- Added `MODIFIER_WEAPON_ENCHANTMENTS` constant for attack damage bonuses due to enchantments like Sharpness.
- Added new API methods `getAttackCooldown()` and `setAttackCooldown()` to allow controlling Living entities attack cooldown times (default 10 ticks).
- `PlayerDeathEvent`: Added new static method `deriveMessage()`.
- `PlayerKickEvent`: Added new method `setReason()`.
#### Forms
- Added a new `pocketmine\form\Form` interface. Implementing this interface permits custom form implementations to make use of `Player->sendForm()`, eliminating the need to handle packets directly and also solving the form ID collision problem.
#### Items
- `Item` and `ItemFactory` now support negative item IDs (needed for future extended blocks support).
- Updated `ItemIds` interface with new constants.
#### Permission
- Added a new `PermissionManager` class which encapsulates all of the permission-management functionality originally bloating `PluginManager`. The API is identical to that of `PluginManager`'s permission API. All methods moved to `PermissionManager` have **`@deprecated`** redirects remaining behind in `PluginManager`, which will be removed in the next major release (4.0).
#### Plugin
- `PluginBase->getConfig()` will now automatically save the default config if it does not already exist.
- Plugin data directories will now be automatically created on plugin load, eliminating the need for boilerplate `@mkdir($this->getDataFolder())` calls at the top of every plugin.
#### Tile
- `Tile::createNBT()` will now throw a `BadMethodCallException` when called directly.
#### Utils
- `Utils::getURL()`, `Utils::postURL()`, `Utils::simpleCurl()` and `Utils::getIP()` have been moved to a new `pocketmine\utils\Internet` class. The original methods are **`@deprecated`** and will be removed for the next major version (4.0).
- Removed the ability for `Config` to be asynchronously saved. This was discussed for removal because of various problems that it causes. It was deemed not worth fixing since `Config` saving should not be significant enough to cause problems anyway. See #2298 for details.
#### Server
- Deprecated `level` parameter of `findEntity()`. This parameter was premature optimization. Code using it will continue to work as before.
### Gameplay
#### General
- Air bubbles are now regenerated at the same speed as vanilla UpdateAquatic, instead of instantly when leaving water.
- Implemented Conduit Power effect.
#### Enchantments
- Implemented the following enchantments: Thorns, Sharpness, Knockback, Fire Aspect, Power, Punch, Flame, Infinity, Mending.
#### Items
- Added the following new items: `Scute`
# 3.2.1
- Fixed `VerifyLoginTask` completion bug when players get disconnected prior to the task completing.
- Fixed client crash issue due to outdated runtime ID mappings.
# 3.2.2
- Updated NBT dependency to 0.2.1 to receive bug fixes (see https://github.com/pmmp/NBT/releases/tag/0.2.1).
# 3.2.3
- Errors thrown during level tick will now crash the server instead of spamming the console.
- Fixed arrows despawning too soon after hitting the ground.
- Fixed projectiles despawning before colliding if they were airborne for > 60 seconds.
- Fixed crash related to Flame enchantment when the player shooting the arrow was on fire.
# 3.2.4
- Fixed levels unloaded during an earlier level's tick on the same tick causing a crash.
- PermissibleBase->clearPermissions() now properly unsubscribes from all permissions.
- Fixed incorrect break check for standing torch.
- Fixed drops for brewing stand.
- Fixed block picking brewing stand, bed, double slab, cake, farmland, and mob heads giving the wrong items.
- Fixed blocks not placing correctly when clicking on redstone ore.
- Fixed unknown PC items in tile inventories crashing the server - now they'll be quietly removed instead.
- Fixed server freezing when eating chorus fruit from high altitude.
- `readline` is now disabled by default on Windows and must be explicitly enabled with `--enable-readline` due to thread-safety issues.
- Fixed server crash when trying to use non-implemented splash potions.
- Removed incorrect maximum region file size cap which may have caused some worlds to be incorrectly detected as corrupted.
# 3.2.5
- `Player->sendForm()` now throws a proper exception when failing to JSON-encode `Form` objects given to it.
- Fixed crash when handling later packets in a batch when an earlier packet triggered termination of the player's connection.
- Fixed a race condition causing progress updates in `AsyncTasks` to be lost when published near completion.
- Fixed bad decoding for some packets with unsupported structures.
- Crash dumps no longer report 20 empty lines when an error occurs in `eval()`'d code.
- `pocketmine/nbt` dependency updated to `0.2.2` to fix bugs (see NBT repo for changelog).
# 3.2.6
- Chunk ticking no longer occurs in chunks which have an adjacent unloaded chunks, fixing things like grass ticking triggering unintentional chunk loading.
- Fixed some lighting propagation issues where step count is the same but light level is different.
- Fixed full-chunk light repopulation producing broken lighting when the generator hasn't been registered on a worker.
- Fixed a missing field in `MoveEntityDeltaPacket`.
- Added client-sided rate limiting for crashdump reporting to mitigate involuntary DDoS of the crash archive.
- Fixed a bug in `start.cmd` where quotes would appear around the "couldn't find installation" message.
# 3.2.7
- Added a network-layer check for item NBT size to avoid unexplained client-sided crashes due to length overflow.
- Fixed some desync bugs with double chests when one half of a double chest is unloaded.
- Anonymous class timings will now have a cleaned path for the identifier relative to the plugins directory.
- Anonymous class timings now render correctly on timings.pmmp.io.
- Fixed empty garbage subchunks not getting removed from long-life chunks.
- `start.ps1`, `start.sh` and `start.cmd` no longer recognize source-code installations. Since source-code installations should only be used by developers who know what they are doing anyway, this was considered unwise to keep.
- Fixed a bug/oversight in network chunk preparation that caused chunk prepare to be 4x slower than necessary.
- `Chunk->fastSerialize()` now doesn't serialize useless data (data is omitted based on chunk flags). This significantly reduces the amount of useless data getting copied for generation, population and light calculation.
- `TaskHandler->cancel()` was incorrectly marked as `@internal` in 2014. This has been fixed. Plugin developers should in fact prefer `TaskHandler->cancel()` since it does not require a task to have a circular dependency on its own executor.

44
changelogs/3.3.md Normal file
View File

@ -0,0 +1,44 @@
**For Minecraft: Bedrock Edition 1.7.0**
### Note
Plugins compatible with any previous 3.x.y version will also run on these releases and do not need API bumps. Plugin developers should **only** update their required API to this version if you need the bug fixes in this build.
# 3.3.0
- Compatibility with Minecraft: Bedrock Edition 1.7.0
- Removed compatibility with 1.6.0
- `Player->sendForm()` now throws a proper exception when failing to JSON-encode `Form` objects given to it.
- Fixed crash when handling later packets in a batch when an earlier packet triggered termination of the player's connection.
- Fixed a race condition causing progress updates in `AsyncTasks` to be lost when published near completion.
- Fixed bad decoding for some packets with unsupported structures.
- Crash dumps no longer report 20 empty lines when an error occurs in `eval()`'d code.
- `pocketmine/nbt` dependency updated to `0.2.2` to fix bugs (see NBT repo for changelog).
# 3.3.1
- Chunk ticking no longer occurs in chunks which have an adjacent unloaded chunks, fixing things like grass ticking triggering unintentional chunk loading.
- Fixed some lighting propagation issues where step count is the same but light level is different.
- Fixed full-chunk light repopulation producing broken lighting when the generator hasn't been registered on a worker.
- Fixed a missing field in `MoveEntityDeltaPacket`.
- Added client-sided rate limiting for crashdump reporting to mitigate involuntary DDoS of the crash archive.
- Fixed a bug in `start.cmd` where quotes would appear around the "couldn't find installation" message.
# 3.3.2
- Added a network-layer check for item NBT size to avoid unexplained client-sided crashes due to length overflow.
- Fixed some desync bugs with double chests when one half of a double chest is unloaded.
- Anonymous class timings will now have a cleaned path for the identifier relative to the plugins directory.
- Anonymous class timings now render correctly on timings.pmmp.io.
- Fixed empty garbage subchunks not getting removed from long-life chunks.
- `start.ps1`, `start.sh` and `start.cmd` no longer recognize source-code installations. Since source-code installations should only be used by developers who know what they are doing anyway, this was considered unwise to keep.
- Fixed a bug/oversight in network chunk preparation that caused chunk prepare to be 4x slower than necessary.
- `Chunk->fastSerialize()` now doesn't serialize useless data (data is omitted based on chunk flags). This significantly reduces the amount of useless data getting copied for generation, population and light calculation.
- `TaskHandler->cancel()` was incorrectly marked as `@internal` in 2014. This has been fixed. Plugin developers should in fact prefer `TaskHandler->cancel()` since it does not require a task to have a circular dependency on its own executor.
# 3.3.3
- Development build error messages are now more user friendly.
- Fixed meta-only changes not getting saved correctly in `SubChunk->setBlock()`.
- Server will now sleep for up to 120 seconds on a crash if the uptime was less than 120 seconds. This delay is intended to reduce crash archive spam and can be skipped by the user if attended by pressing CTRL+C.
- Fixed preprocessed builds sometimes having `new ` calls treated as function calls.
- Fixed a rare corruption case where player data could be written incorrectly due to a race condition.
- `DataPacket` will now throw errors when attempting to read/write nonexisting fields to make it easier to debug protocol change errors.
# 3.3.4
- Fixed an undefined `DataPacket` field making the previous release unusable.

97
changelogs/3.4.md Normal file
View File

@ -0,0 +1,97 @@
**For Minecraft: Bedrock Edition 1.7.0**
This is a cumulative minor release featuring performance improvements, memory usage improvements, some new minor gameplay features, some API deprecations and additions, and significant changes to error handling.
### Note
Plugins compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
However, some API features have been deprecated in this version. Plugin developers do not need to do anything about these deprecations immediately, however they may raise harmless warnings if used.
Features marked **`@deprecated`** are **recommended** not to be used, but will continue to work for any future 3.x.y versions. They will be removed in the next major release (4.0).
# 3.4.0
## Core changes
### Performance & memory improvements
- Entity `EXHAUSTION` attribute is no longer synced to the client, which reduces network traffic for survival players and reduces client-sided lag.
- A redundant call was removed from an `Event` call hot path which improves event calling performance by ~15% per event handler executed.
- Light updates are now batched together and executed on the end of each tick. The effects of this are noticeable when setting a large number of blocks in a close area - significant performance improvements should be noticeable for world editors (the ones that didn't disable light updates) and liquid flow is now significantly less expensive.
- Internal enhancements have been made to subchunk light array interfacing to reduce branching and improve access performance.
- Memory usage of most chunks has dropped by ~30-40% due to some improvements to internal storage of unlit subchunks. In real terms this translates to ~30% memory usage reduction for a freshly generated world.
### Error handling
The most notable core change in this release revolves around error handling. Internals have been cleaned up substantially to improve the server behaviour under occurrence of unexpected behaviour. The goal of this is to improve consistency and quality while reducing undefined runtime behaviour.
The following changes have been made:
- Throwing **unexpected** `Throwable`s in the following cases will now cause a server crash (except on network (this will be changed in the future)):
- Event handlers
- `Task->onRun()` on a scheduler
- `AsyncTask->onCompletion()`
- `Command->execute()` and `CommandExecutor->onCommand()`
- Unexpected `Throwable`s thrown during packet handling will now cause the target player to be disconnected with an `Internal server error` message.
### Other changes
- Anti-flight has been removed, along with the `allow-flight` directive in `server.properties`.
- Server language is now controlled by the `language` directive in `server.properties`.
- Added `unban` and `unban-ip` as aliases of `pardon` and `pardon-ip` commands respectively.
## API changes
### Block
- `BlockSpreadEvent` is now fired when lava or water tries to flow into a block.
- `BlockFormEvent` is now fired when lava and water collide to form cobblestone, obsidian or stone.
### Event
- Added new method `Event->call()`. This should be used instead of `PluginManager->callEvent()` in plugins only supporting 3.4+.
- `PluginManager->callEvent()` has been `@deprecated`.
### Level
- Attempting to unload a level during its tick will now throw an `InvalidStateException`.
- Added the following new methods:
- `Level->broadcastPacketToViewers()`
- `Level->getViewersForPosition()`
- `Level->broadcastGlobalPacket()`
- `Level->getChunkAtPosition()`
- `Level->isInLoadedTerrain()`
- `Level->addGlobalPacket()` has been `@deprecated`.
- `LightUpdate` now allows calling `setAndUpdateLight()` for the same position multiple times (needed for light update batching).
### Permission
- `Permission::getByName()` now throws an exception on invalid values instead of silently returning `DEFAULT_FALSE`. This may cause new errors to appear if your plugins had broken permission defaults in `plugin.yml`.
### Player
- `addWindow()` now has stricter validity checks and will now throw exceptions in the following cases: No window IDs left to use, and when a forced window ID collides with an existing window.
- The public `$speed` field has been removed (this was only used by anti-cheat which has now been removed).
### Scheduler
- `AsyncTask->setResult()` has had the `$serialize` parameter removed - now it will automatically serialize (or not) as appropriate.
- Added a new `ClosureTask` which allows concisely scheduling closure execution on a `TaskScheduler`.
- `TaskScheduler->__construct()` `$logger` parameter has been `@deprecated` and will be removed in a future major version.
### Server
- Added new method `Server->hasOfflinePlayerData(string $name) : bool`.
- `Server->getAllowFlight()` has been `@deprecated`.
### Utils
- `Config->save()` will no longer catch unexpected exceptions thrown while encoding data.
## Gameplay changes
### Blocks
- Rail connectivity has been implemented for normal, powered, detector and activator rails (but there are currently no minecarts).
# 3.4.1
- Updated crashdump format to be compatible with newest CA. This version or newer is required if you want to be able to submit crashdumps to crash.pmmp.io.
# 3.4.2
- `DataPacket` errors when writing to undefined fields are now more clear.
- Fixed trees being able to overwrite the log parts of other trees.
- Fixed `Player->sendForm()` not working during `PlayerJoinEvent`.
- `Entity->setScale()` now explicitly requires a scale larger than 0.
- Adding invisible `FloatingTextParticle` to a level no longer causes an error.
# 3.4.3
- Fixed burning TNT setting hurt entities on fire when exploding.
- `~` relative coordinates now work in the `/particle` command.
- Various boring fixes to error stack trace reporting.
- `Level->setChunk()` no longer deletes tiles and entities when replacing a chunk with itself.
- Fixed a generator race condition causing rare appearances of half-trees on the client in freshly generated terrain.
- `Attribute->resetToDefault()` now fits the default per the min/max bounds, fixing crashes when the bounds are changed to exclude the default.
- Fixed a crash with LevelDB worlds when the `TAG_2D_MAPS` tag is missing.
- Fixed `Utils::getCoreCount()` crashing on some Debian variants.

149
changelogs/3.5.md Normal file
View File

@ -0,0 +1,149 @@
**For Minecraft: Bedrock Edition 1.8.0**
### Note
Plugins compatible with any previous 3.x.y version will also run on these releases and do not need API bumps. Plugin developers should **only** update their required API to this version if you need the changes in this build.
# 3.5.0
- Compatibility with Minecraft: Bedrock Edition 1.8.0
- Removed compatibility with 1.7.0
# 3.5.1
- Fixed internal server errors when attempting to craft.
- `DataPacket` errors when writing to undefined fields are now more clear.
- Fixed trees being able to overwrite the log parts of other trees.
- Fixed `Player->sendForm()` not working during `PlayerJoinEvent`.
- `Entity->setScale()` now explicitly requires a scale larger than 0.
- Adding invisible `FloatingTextParticle` to a level no longer causes an error.
# 3.5.2
- Updated some misc protocol magic numbers.
- Fixed burning TNT setting hurt entities on fire when exploding.
- `~` relative coordinates now work in the `/particle` command.
- Various boring fixes to error stack trace reporting.
- `Level->setChunk()` no longer deletes tiles and entities when replacing a chunk with itself.
- Fixed a generator race condition causing rare appearances of half-trees on the client in freshly generated terrain.
- `Attribute->resetToDefault()` now fits the default per the min/max bounds, fixing crashes when the bounds are changed to exclude the default.
- Fixed a crash with LevelDB worlds when the `TAG_2D_MAPS` tag is missing.
- Fixed `Utils::getCoreCount()` crashing on some Debian variants.
# 3.5.3
- Rewritten documentation of `PlayerPreLoginEvent`, `PlayerLoginEvent` and `PlayerJoinEvent`. They are now much more detailed and no longer misleading.
- Chest items block-picked from double chests will no longer place chests that crash the server when opened.
- Ender chests now make the correct sounds when opening and closing.
- Fixed Sign errors when a buggy or malicious client sent broken NBT with the wrong tags or wrong number of lines.
- Resource packs with comments in the manifest will now load correctly. (MOJANG!!!)
- Placement of unknown blocks is now disallowed. This solves a range of problems with invalid blocks in the world, such as #2260 .
- Errors thrown during `PlayerQuitEvent` or other `Player->close()` errors will now crash the server instead of causing cryptic bugs later on.
- Fixed large chunks (>= 1044476 bytes) becoming corrupted when saved in Region-based worlds - now an exception is thrown instead.
- Reduced the range of exceptions caught during chunk loading. Now, only chunk corruption errors are caught, and anything else will produce a crash.
- Removed catch-all block on chunk saving. Unexpected errors thrown during chunk save will now create a crash.
- Fixed some asserts in packet decode methods.
- `Attribute` now throws exceptions with more informative messages on errors.
- Properly handled some remaining `Uninitialized string offset` bugs when decoding packets.
- Fixed chunk updates taking several seconds to show up on the client. This bug was most apparent during generation and some world editing tools using asynchronous tasks.
- Fixed CPU waste ordering chunks for non-moving players.
# 3.5.4
### Fixes
- Fixed server crash when a block update occurs on a torch with corrupted metadata.
- Added a hack to mitigate client-side right-click spam bug. This mostly eliminates spam of `PlayerInteractEvent` on right-click.
- Players will no longer see commands they don't have permission to use in client-sided hints when typing a `/` in the chat window.
- `Event->isCancelled()` and `Event->setCancelled()` now throw more informative errors.
- Errors thrown during a network interface processing will now _actually_ crash the server.
### API changes
- Deprecated `NetworkInterfaceCrashEvent`. Nobody should have been using this anyway.
- Deprecated `Network->processInterface()`
- Deprecated `SourceInterface->emergencyShutdown()`
# 3.5.5
- Mobs no longer spawn with their heads facing a different direction to their bodies.
- Added a console message when the crash strangler sleeps to stop crash spam.
- Fixed crash in `/title` command `times` subcommand when not enough arguments were passed.
- AsyncWorkers will now not be shut down on GC unless they have not been used for the last 5 minutes. This reduces lag spikes on garbage collection.
- Fixed some unhandled error cases in `AddEntityPacket` encoding.
- Fixed `LogicException` descendents being thrown from some packet decoding methods when encountering bad userdata.
- Player network inventory transaction processing now catches more specific errors.
- Fixed missing decode for `TakeItemEntityPacket`.
- Fixed `/gc` and `/status` truncating memory statistics - now they report to 0.01 precision.
- Global functions and constants are now imported to improve performance.
- Fixed a typo in `pocketmine.command.op.take` description.
- Ice no longer creates water when a creative player breaks it.
- `spawn-mobs` and `spawn-animals` no longer appear in generated `server.properties` on a newly-installed server.
- Added a hack to disable pre-spawn client-sided movement.
- Assertions enabled warning now always shows when `zend.assertions` is not `-1`. The config option to disable this warning has been removed.
- `/status`,`/dumpmemory` and `/gc` are now enabled by default. The `debug.commands` config option has been removed.
- Crash dumps are now more thorough at catching plugin-related crashes.
# 3.5.6
- Fixed `#`-commenting properties in `.properties` files not working.
- `pocketmine.yml` now permits writing `worldname:` with no generation settings in the `worlds` section to force a world to be loaded.
- Fixed Bow force being too low - now it's consistent with Minecraft Java (but not with Bedrock due to a vanilla bug).
- Fixed `recursion detected` bug when encoding crashdumps in some cases.
- Items with too-large NBT tags on network will now have their tags ignored when sending over network, instead of crashing the server. This is a workaround for a protocol bug which will be addressed in a future Minecraft release.
- `/enchant` no longer crashes the server when out-of-bounds enchantment levels are used.
- Fixed some crashes loading Region-based worlds when encountering unexpected EOF.
- `Entity->fireTicks` is now protected (but accessible by magic method for BC purposes) and will now throw an exception when written to if the value is > 32767 or < 0.
- Fixed Signs asserting on corrupted world data with more than 4 lines of text per sign.
# 3.5.7
- Fixed several bugs in RCON packet receive that would allow an attacker to block or crash the RCON thread, denying service to other legitimate RCON clients.
- Fixed RCON connections not working (timing out with no response) on some platforms.
- Logins are now permitted to have up to 60 seconds clock drift on the `nbf` and `exp` timestamps in the login JWT.
- Fixed XP orbs following players who switched to a location spatially nearby in a different world.
- `Player->removeWindow()` now throws `InvalidArgumentException` instead of `BadMethodCallException` when trying to non-forcefully remove a fixed window ID.
# 3.5.8
- Fixed player XP not dropping if a player was fast enough to respawn.
- Player XP drop amount now matches vanilla (7x level points, incurs some loss of points for higher levels)
- Fixed Doxygen configuration including test sources.
- Improved performance of block-cache accesses.
- Improved performance of random block-ticking.
- Closure tasks will now show the correctly formatted name on timings.
- Fixed a crash when a local update happens next to an `ItemFrame` with invalid metadata.
- Fixed player being subscribed to broadcast permissions too early when permissions are modified before spawn.
- Block-picking is now disallowed on unknown blocks.
- Internal IP detection now works correctly on all platforms.
- Fixed UPnP portforwarding not working correctly when multiple network adapters are installed.
- Starting or stopping flight now resets fall distance and in-air ticks.
- Fixed falling causing starvation.
- Fixed crops consuming bone meal when fully grown.
- Users are no longer able to avoid agreeing to the license by restarting the server.
- Explosions no longer create broken double chests which crash the server. Existing chests affected by this bug will continue to crash. This will be addressed in a future release.
- Cactus and sugarcane no longer grow through non-air blocks.
- Fixed a memory leak in `setChunk()` when the `unload` parameter is true.
- Generator will now crash if preset is invalid, instead of producing unexpected results.
# 3.5.9
- Fixed a `setChunk()` bug introduced by 3.5.8.
- Applied a hack to disable client-sided automatic regeneration.
- `Level->getChunkPlayers()` is now deprecated.
# 3.5.10
- Some internal `Level` functions are now correctly marked `@internal`.
- Fixed splash potion distance being measured from player feet instead of eye height.
- Fixed tall grass being unplaceable on dirt.
- A debug message is now recorded when a chunk is loaded with no associated loaders.
- Composer dependencies have been updated to fix bugs in some dependencies.
# 3.5.11
- Fixed crashing when items with negative IDs are found in the inventory (caused by downgrading from dev builds).
- Updated creative inventory and crafting recipes.
# 3.5.12
- Fixed crash when too-large values are given to `/effect` for duration.
- `/op` and other commands no longer crash when an invalid player name is given.
- Startup time no longer includes the time spent in the setup wizard.
- `TextFormat::clean()` is now UTF-8 aware, and will scrub any invalid UTF-8 characters from the given string.
- Fixed `TextFormat::clean()` not fully removing ANSI escape codes in some cases.
- Fixed Korean command arguments failing to parse.
- `Sign->setText()` and `Sign->setLine()` now enforce that the given text must be UTF-8 text, or an exception will be thrown.
- Sign text is now processed by `mb_scrub()` immediately after loading to remove invalid UTF-8 characters that could crash the client.
- `Human->exhaust()` no longer underflows when the hunger attribute has a fractional value.
# 3.5.13
- Added a hack to disable client sided AI for non-moving entities. This fixes items floating in water despite it not being implemented server-side yet.
- Fixed max health not working as expected on respawn if changed by plugins.
- Fixed Item Frame hardness (0.25 instead of 0).
- Fire Aspect tools will now light TNT when right-clicked with.
- Fixed incorrect nullable typehints on `TaskScheduler` return values.

65
changelogs/3.6.md Normal file
View File

@ -0,0 +1,65 @@
**For Minecraft: Bedrock Edition 1.9.0**
### Note
Plugins compatible with any previous 3.x.y version will also run on these releases and do not need API bumps. Plugin developers should **only** update their required API to this version if you need the changes in this build.
This changelog **does not account for protocol changes**. If your plugin uses the protocol, you're not shielded by API change constraints.
# 3.6.0
- Compatibility with Minecraft: Bedrock Edition 1.9.0
- Removed compatibility with 1.8.0
- `Item->getCompoundTag()` is now `@deprecated`.
- `Item->setCompoundTag()` now accepts NULL as a possible value.
- `ItemFactory::fromString()` now accepts NULL for the `tags` parameter.
# 3.6.1
- Fixed crashing when items with negative IDs are found in the inventory (caused by downgrading from dev builds).
- Updated creative inventory and crafting recipes.
- Fixed handling for some new blocks which magically appeared without appropriate implementations (extra meta values).
# 3.6.2
- Fixed client-sided crash when upper-case letters appear in command names.
- Fixed crash when too-large values are given to `/effect` for duration.
- `/op` and other commands no longer crash when an invalid player name is given.
- Startup time no longer includes the time spent in the setup wizard.
- `TextFormat::clean()` is now UTF-8 aware, and will scrub any invalid UTF-8 characters from the given string.
- Fixed `TextFormat::clean()` not fully removing ANSI escape codes in some cases.
- Fixed Korean command arguments failing to parse.
- `Sign->setText()` and `Sign->setLine()` now enforce that the given text must be UTF-8 text, or an exception will be thrown.
- Sign text is now processed by `mb_scrub()` immediately after loading to remove invalid UTF-8 characters that could crash the client.
- `Human->exhaust()` no longer underflows when the hunger attribute has a fractional value.
# 3.6.3
- Added a hack to disable client sided AI for non-moving entities. This fixes items floating in water despite it not being implemented server-side yet.
- Fixed max health not working as expected on respawn if changed by plugins.
- Fixed Item Frame hardness (0.25 instead of 0).
- Fire Aspect tools will now light TNT when right-clicked with.
- Fixed incorrect nullable typehints on `TaskScheduler` return values.
# 3.6.4
- `NetworkStackLatencyPacket` unhandled debug has been silenced.
- Fixed `Player->removeWindow()` removing GUI or crashing clients when removing a window which was not added.
- Fixed packed ice dropping itself when mined without a silk touch pickaxe.
- Fixed players not taking fall damage when falling off the side of a ladder when their AABB was intersecting with the ladder's full block area.
- Fixed arrows reloaded from disk never despawning.
- Fixed player XP not dropping on death.
- Fixed player's held slot being out of sync when respawning.
- Fixed items with different NBT being considered stackable in some cases by `BaseInventory->canAddItem()`.
# 3.6.5
- Fixed stdout silence on crash if a crash occurs when PHP output buffering is enabled.
- Fixed `RegionLoader` considering a range of invalid chunk coordinates as valid.
- Fixed `RegionLoader` causing region header corruption when an oversized chunk was discovered. This was causing entire regions to be discarded next time they were freshly loaded.
- Fixed performance issue loading old LevelDB worlds (from before MCPE 1.0) due to unmodified chunks being converted every time they were loaded.
- Added new debug messages when a world takes too long (longer than 50ms) to complete a tick.
- Debug messages are now logged when autosave kicks in (with time measurements), which helps debugging unexplained lag spikes.
- Level "auto tick rate" anti-feature and its associated `pocketmine.yml` settings have been removed (see #2665). The settings will persist in old configurations, but will be ignored by this version and future versions.
- The `/save-all` command now outputs custom (non-vanilla) messages informing the user how long it took to complete autosaving.
- The word `level` has been replaced with `world` (where appropriate) throughout language strings and general user interface messages.
# 3.6.6
- Fixed protocol argument types for commands.
- Autosave debug message will now report in milliseconds when the time taken is less than 1 second.
- Flatworld presets now allow `*` as a multiplier symbol (fixes PC compatibility).
- Network runtimeIDs for blocks are now randomized to prevent things (like plugins) relying on them.
- Updated NBT dependency to 0.2.7 for some bug fixes.

33
changelogs/3.7.md Normal file
View File

@ -0,0 +1,33 @@
**For Minecraft: Bedrock Edition 1.10.0**
### Note
Plugins compatible with any previous 3.x.y version will also run on these releases and do not need API bumps. Plugin developers should **only** update their required API to this version if you need the changes in this build.
This changelog **does not account for protocol changes**. If your plugin uses the protocol, you're not shielded by API change constraints.
# 3.7.0
- Compatibility with Minecraft: Bedrock Edition 1.10.0
- Removed compatibility with 1.9.0
# 3.7.1
- Fixed protocol argument types for commands.
- Autosave debug message will now report in milliseconds when the time taken is less than 1 second.
- Flatworld presets now allow `*` as a multiplier symbol (fixes PC compatibility).
- Network runtimeIDs for blocks are now randomized to prevent things (like plugins) relying on them.
- Updated NBT dependency to 0.2.7 for some bug fixes.
# 3.7.2
- Fixed a memory leak when `PlayerLoginEvent` is cancelled.
- Fixed permissions `pocketmine.command.ban.list`, `pocketmine.command.difficulty`, `pocketmine.command.whitelist.enable` and `pocketmine.command.whitelist.disable` always being granted to operators.
- Fixed some commands outputting `commands.generic.permission` instead of the proper message when running commands that the sender doesn't have permission to use.
- Worlds with unknown generator types will now refuse to load instead of getting incorrect terrain generation ruining them.
- `TextFormat::tokenize()` no longer corrupts Unicode sequences.
- `TextFormat::clean()` now removes non-printable Unicode code points in the private-use area.
- Running two servers in the same data directory is no longer allowed and will gracefully halt instead of corrupting your data.
- Sign text length is now soft-capped at 1000 characters.
# 3.7.3
- World save timings now include saves that are triggered by chunk unloading.
- Fixed several network denial-of-service bugs.
- A warning is now emitted when the `ChunkUtils` extension is not loaded.
- Moved version constants to a separate `VersionInfo` file for easier parsing and handling.

69
changelogs/3.8.md Normal file
View File

@ -0,0 +1,69 @@
**For Minecraft: Bedrock Edition 1.11.0**
### Note
Plugins compatible with any previous 3.x.y version will also run on these releases and do not need API bumps. Plugin developers should **only** update their required API to this version if you need the changes in this build.
This changelog **does not account for protocol changes**. If your plugin uses the protocol, you're not shielded by API change constraints.
# 3.8.0
- Compatibility with Minecraft: Bedrock Edition 1.11.0
- Removed compatibility with 1.10.0
# 3.8.1
- Fixed furnace smelting recipes not working.
- Reduced legacy hacks dealing with `BatchPacket` to fix possible ID collisions.
- Reduced release phar size by minifying JSON data blobs.
- Moved some MCPE-specific JSON blobs to submodule.
# 3.8.2
- Fixed --enable-ansi and --disable-ansi not being respected on threads.
- Fixed a crash that could occur when decoding `AvailableCommandsPacket`.
- Fixed a crash when loading worlds with entities with missing `Motion` NBT tag.
- Fixed a crash when world time overflows signed int64 max.
- Fixed world generators and providers being registered too late (this was causing plugin issues).
- Updated RakLib version to get a security fix.
- Fixed errors when custom clients fill the wrong information in `ResourcePackClientResponsePacket`.
- Fixed `setImmobile()` getting overridden directly after `PlayerJoinEvent`.
- Fixed air being breakable by creative players.
- Fixed performance loss caused by bugs in the preprocessor.
# 3.8.3
- Fixed infinite recursion when using `Entity->close()` during `EntityDespawnEvent`.
- Fixed crash reports caused by folder plugins being reported to the crash archive.
- Fixed spawning entities on unloaded chunks during spawn sequence (possible client crash cause).
- Fixed `/time query` output message.
- Fixed `Server->hasOfflinePlayerData()` being case-sensitive.
- Improved error messages for skin validation in some places.
- Fixed classic stonecutter hardness.
- Fixed iron trapdoors being considered a valid furnace fuel.
- Fixed apple dropping from leaves happening less frequently than intended.
- Fixed tall plants like sunflower being replaceable by the top half.
# 3.8.4
- Plugin load order is now randomised to remove the ability to implicitly depend on filesystem-specific ordering.
- Packet logging in debug messages now uses base64 instead of hex (uses less space).
- Array and string size are now shown in error stack trace logs.
- Stack traces now render a maximum of 80 characters when making string parameters printable.
- Improved documentation for some transaction classes.
- Action order in inventory transactions is now randomised to prevent dependencies on any accidental or client-dependent ordering. Since the transaction system is specifically designed to avoid depending on order, this does not affect any core functionality.
# 3.8.5
- Moved preprocessor to build/ directory.
- Added documentation for `Server->getPlayer()`, `Server->getPlayerExact()` and `Server->matchPlayer()`.
- `server.lock` now contains the PID of the currently-running server.
- PID of server is now reported in the error message when attempting to run two servers from the same data directory at once.
- Fixed sluggish playercount updating on MOTD.
- Added new MultiRecipe UUIDs.
- Added an extra field to `StartGamePacket` to resolve minor incompatibility issues on different 1.11.x patch versions.
# 3.8.6
- Fixed `Entity->isNameTagAlwaysVisible()` not working.
- Log messages are now cleaned of invalid UTF-8 sequences before emitting them.
- Fixed negative integers being considered as strings for world seeds.
- Fixed out-of-bounds access on invalid inventory data in player data saves.
- Fixed crash when custom liquids have flow decays which aren't factors of 4.
- Fixed `Entity->noDamageTicks` not working when the entity had no previous damage cause.
# 3.8.7
- Improved documentation of `Player->getDisplayName()` and `Player::isValidUserName()`.
- Fixed a bug in `SetScorePacket` decoding causing the entry list to always be empty.

46
changelogs/3.9.md Normal file
View File

@ -0,0 +1,46 @@
**For Minecraft: Bedrock Edition 1.12.0**
### Note about API versions
Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps.
Plugin developers should **only** update their required API to this version if you need the changes in this build.
**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do.
# 3.9.0
- Added support for Minecraft: Bedrock Edition 1.12.0
- Removed compatibility with 1.11.0
## Protocol
- The following classes in the `\pocketmine\network\mcpe\protocol` namespace have been renamed:
- `AddEntityPacket` -> `AddActorPacket`
- `AddItemEntityPacket` -> `AddItemActorPacket`
- `AvailableEntityIdentifiersPacket` -> `AvailableActorIdentifiersPacket`
- `BlockEntityDataPacket` -> `BlockActorDataPacket`
- `EntityEventPacket` -> `ActorEventPacket`
- `EntityFallPacket` -> `ActorFallPacket`
- `EntityPickRequestPacket` -> `ActorPickRequestPacket`
- `MoveEntityAbsolutePacket` -> `MoveActorAbsolutePacket`
- `MoveEntityDeltaPacket` -> `MoveActorDeltaPacket`
- `RemoveEntityPacket` -> `RemoveActorPacket`
- `SetEntityDataPacket` -> `SetActorDataPacket`
- `SetEntityLinkPacket` -> `SetActorLinkPacket`
- `SetEntityMotionPacket` -> `SetActorMotionPacket`
- `TakeItemEntityPacket` -> `TakeItemActorPacket`
- The following classes in the `\pocketmine\network\mcpe\protocol` namespace have been removed:
- `FullChunkDataPacket`
- The following classes in the `\pocketmine\network\mcpe\protocol` namespace have been added:
- `AddEntityPacket` (not to be confused with the old one)
- `ClientCacheBlobStatusPacket`
- `ClientCacheMissResponsePacket`
- `ClientCacheStatusPacket`
- `LevelChunkPacket`
- `RemoveEntityPacket` (not to be confused with the old one)
- `StructureTemplateDataExportRequestPacket`
- `StructureTemplateDataExportResponsePacket`
# 3.9.1
- Fixed resource packs not working on 1.12 clients.
- Fixed some particles displaying incorrectly (some still don't render at all).
- Fixed `Entity->setFireTicks()` with a value of `0` setting the on-fire flag.
- Silenced a debug message which appeared every time a player right-clicked a block.
- Updated constants for `LevelSoundEventPacket`.

24
composer.lock generated
View File

@ -160,16 +160,16 @@
},
{
"name": "pocketmine/nbt",
"version": "0.2.6",
"version": "0.2.7",
"source": {
"type": "git",
"url": "https://github.com/pmmp/NBT.git",
"reference": "92eaf84dd61f700d3ec02ebd01b606cb5b1590d4"
"reference": "2f176c9f2fd9b31db8bc2ada2f38990157ec8f1a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/92eaf84dd61f700d3ec02ebd01b606cb5b1590d4",
"reference": "92eaf84dd61f700d3ec02ebd01b606cb5b1590d4",
"url": "https://api.github.com/repos/pmmp/NBT/zipball/2f176c9f2fd9b31db8bc2ada2f38990157ec8f1a",
"reference": "2f176c9f2fd9b31db8bc2ada2f38990157ec8f1a",
"shasum": ""
},
"require": {
@ -194,23 +194,23 @@
],
"description": "PHP library for working with Named Binary Tags",
"support": {
"source": "https://github.com/pmmp/NBT/tree/0.2.6",
"source": "https://github.com/pmmp/NBT/tree/0.2.7",
"issues": "https://github.com/pmmp/NBT/issues"
},
"time": "2019-02-07T16:28:11+00:00"
"time": "2019-03-29T19:39:42+00:00"
},
{
"name": "pocketmine/raklib",
"version": "0.12.2",
"version": "0.12.4",
"source": {
"type": "git",
"url": "https://github.com/pmmp/RakLib.git",
"reference": "54a36d55eeba0a182e00439920ee2fcfa8c72bf3"
"reference": "fc1ccc8e61b9033e5372436b2e28a7a95388373f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/54a36d55eeba0a182e00439920ee2fcfa8c72bf3",
"reference": "54a36d55eeba0a182e00439920ee2fcfa8c72bf3",
"url": "https://api.github.com/repos/pmmp/RakLib/zipball/fc1ccc8e61b9033e5372436b2e28a7a95388373f",
"reference": "fc1ccc8e61b9033e5372436b2e28a7a95388373f",
"shasum": ""
},
"require": {
@ -235,10 +235,10 @@
],
"description": "A RakNet server implementation written in PHP",
"support": {
"source": "https://github.com/pmmp/RakLib/tree/0.12",
"source": "https://github.com/pmmp/RakLib/tree/0.12.4",
"issues": "https://github.com/pmmp/RakLib/issues"
},
"time": "2019-01-21T14:17:30+00:00"
"time": "2019-05-02T14:53:51+00:00"
},
{
"name": "pocketmine/snooze",

File diff suppressed because it is too large Load Diff

10
doxygen/index.md Normal file
View File

@ -0,0 +1,10 @@
## PocketMine-MP API Documentation
This site contains auto-generated API documentation for PocketMine-MP (and dependencies which are not outsourced). Documentation here is regenerated for every release.
This site can be accessed via https://apidoc.pmmp.io.
### Additional developer resources
- [DevTools](https://github.com/pmmp/PocketMine-DevTools/) - Development tools plugin for creating plugins
- [ExamplePlugin](https://github.com/pmmp/ExamplePlugin/) - Example plugin demonstrating some basic API features
- [DeveloperDocs](https://github.com/pmmp/DeveloperDocs/) - Reference, guides and specifications for the PocketMine-MP API

View File

@ -99,19 +99,20 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\network\mcpe\PlayerNetworkSessionAdapter;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use pocketmine\network\mcpe\protocol\AnimatePacket;
use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket;
use pocketmine\network\mcpe\protocol\AvailableCommandsPacket;
use pocketmine\network\mcpe\protocol\AvailableEntityIdentifiersPacket;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\BlockEntityDataPacket;
use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket;
use pocketmine\network\mcpe\protocol\BlockActorDataPacket;
use pocketmine\network\mcpe\protocol\BlockPickRequestPacket;
use pocketmine\network\mcpe\protocol\BookEditPacket;
use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\DisconnectPacket;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\InteractPacket;
use pocketmine\network\mcpe\protocol\InventoryTransactionPacket;
use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket;
@ -210,7 +211,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
public const VIEW = Player::SPECTATOR;
/**
* Checks a supplied username and checks it is valid.
* Validates the given username.
*
* @param string $name
*
@ -392,7 +393,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
public function isBanned() : bool{
return $this->server->getNameBans()->isBanned($this->iusername);
return $this->server->getNameBans()->isBanned($this->username);
}
public function setBanned(bool $value){
@ -405,14 +406,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
public function isWhitelisted() : bool{
return $this->server->isWhitelisted($this->iusername);
return $this->server->isWhitelisted($this->username);
}
public function setWhitelisted(bool $value){
if($value){
$this->server->addWhitelist($this->iusername);
$this->server->addWhitelist($this->username);
}else{
$this->server->removeWhitelist($this->iusername);
$this->server->removeWhitelist($this->username);
}
}
@ -720,7 +721,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
$data = new CommandData();
$data->commandName = $command->getName();
//TODO: commands containing uppercase letters in the name crash 1.9.0 client
$data->commandName = strtolower($command->getName());
$data->commandDescription = $this->server->getLanguage()->translateString($command->getDescription());
$data->flags = 0;
$data->permission = 0;
@ -798,7 +800,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
/**
* Gets the "friendly" name to display of this player to use in the chat.
* Returns the "friendly" display name of this player to use in the chat.
*
* @return string
*/
@ -1063,6 +1065,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return; //avoid player spawning twice (this can only happen on 3.x with a custom malicious client)
}
$this->spawned = true;
$this->setImmobile(false);
if($this->hasPermission(Server::BROADCAST_CHANNEL_USERS)){
PermissionManager::getInstance()->subscribeToPermission(Server::BROADCAST_CHANNEL_USERS, $this);
@ -1081,10 +1084,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->server->broadcastMessage($ev->getJoinMessage());
}
$this->setImmobile(false);
$this->noDamageTicks = 60;
foreach($this->usedChunks as $index => $c){
foreach($this->usedChunks as $index => $hasSent){
if(!$hasSent){
continue; //this will happen when the chunk is ready to send
}
Level::getXZ($index, $chunkX, $chunkZ);
foreach($this->level->getChunkEntities($chunkX, $chunkZ) as $entity){
if($entity !== $this and !$entity->isClosed() and $entity->isAlive() and !$entity->isFlaggedForDespawn()){
@ -1929,7 +1934,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return true;
}
if(!$this->server->isWhitelisted($this->iusername) and $this->kick("Server is white-listed", false)){
if(!$this->server->isWhitelisted($this->username) and $this->kick("Server is white-listed", false)){
return true;
}
@ -2059,7 +2064,13 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
case ResourcePackClientResponsePacket::STATUS_SEND_PACKS:
$manager = $this->server->getResourcePackManager();
foreach($packet->packIds as $uuid){
$pack = $manager->getPackById(substr($uuid, 0, strpos($uuid, "_"))); //dirty hack for mojang's dirty hack for versions
//dirty hack for mojang's dirty hack for versions
$splitPos = strpos($uuid, "_");
if($splitPos !== false){
$uuid = substr($uuid, 0, $splitPos);
}
$pack = $manager->getPackById($uuid);
if(!($pack instanceof ResourcePack)){
//Client requested a resource pack but we don't have it available on the server
$this->close("", "disconnectionScreen.resourcePack", true);
@ -2099,6 +2110,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
/** @var float[] $pos */
$pos = $this->namedtag->getListTag("Pos")->getAllValues();
$this->level->registerChunkLoader($this, ((int) floor($pos[0])) >> 4, ((int) floor($pos[2])) >> 4, true);
$this->usedChunks[Level::chunkHash(((int) floor($pos[0])) >> 4, ((int) floor($pos[2])) >> 4)] = false;
parent::__construct($this->level, $this->namedtag);
$ev = new PlayerLoginEvent($this, "Plugin reason");
@ -2145,7 +2157,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$pk->worldName = $this->server->getMotd();
$this->dataPacket($pk);
$this->sendDataPacket(new AvailableEntityIdentifiersPacket());
$this->sendDataPacket(new AvailableActorIdentifiersPacket());
$this->sendDataPacket(new BiomeDefinitionListPacket());
$this->level->sendTime($this);
@ -2266,14 +2279,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return true;
}
public function handleEntityEvent(EntityEventPacket $packet) : bool{
public function handleEntityEvent(ActorEventPacket $packet) : bool{
if(!$this->spawned or !$this->isAlive()){
return true;
}
$this->doCloseInventory();
switch($packet->event){
case EntityEventPacket::EATING_ITEM:
case ActorEventPacket::EATING_ITEM:
if($packet->data === 0){
return false;
}
@ -2842,6 +2855,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
case PlayerActionPacket::ACTION_STOP_SWIMMING:
//TODO: handle this when it doesn't spam every damn tick (yet another spam bug!!)
break;
case PlayerActionPacket::ACTION_INTERACT_BLOCK: //ignored (for now)
break;
default:
$this->server->getLogger()->debug("Unhandled/unknown player action type " . $packet->action . " from " . $this->getName());
return false;
@ -2968,7 +2983,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
return $handled;
}
public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{
public function handleBlockEntityData(BlockActorDataPacket $packet) : bool{
if(!$this->spawned or !$this->isAlive()){
return true;
}
@ -2982,7 +2997,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$t = $this->level->getTile($pos);
if($t instanceof Spawnable){
$nbt = new NetworkLittleEndianNBTStream();
$compound = $nbt->read($packet->namedtag);
$_ = 0;
$compound = $nbt->read($packet->namedtag, false, $_, 512);
if(!($compound instanceof CompoundTag)){
throw new \InvalidArgumentException("Expected " . CompoundTag::class . " in block entity NBT, got " . (is_object($compound) ? get_class($compound) : gettype($compound)));
@ -3298,7 +3314,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
/**
* Resets the title duration settings.
* Resets the title duration settings to defaults and removes any existing titles.
*/
public function resetTitles(){
$pk = new SetTitlePacket();
@ -3626,7 +3642,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
if($this->inventory !== null){
$this->inventory->setHeldItemIndex(0, false); //This is already handled when sending contents, don't send it twice
$this->inventory->setHeldItemIndex(0);
$this->inventory->clearAll();
}
if($this->armorInventory !== null){
@ -3634,8 +3650,12 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
}
//TODO: allow this number to be manipulated during PlayerDeathEvent
$this->level->dropExperience($this, $this->getXpDropAmount());
$this->setXpAndProgress(0, 0);
if($ev->getDeathMessage() != ""){
$this->server->broadcast($ev->getDeathMessage(), Server::BROADCAST_CHANNEL_USERS);
$this->server->broadcastMessage($ev->getDeathMessage());
}
}
@ -3903,8 +3923,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
throw new \InvalidArgumentException("Cannot remove fixed window $id (" . get_class($inventory) . ") from " . $this->getName());
}
$inventory->close($this);
if($id !== null){
$inventory->close($this);
unset($this->windows[$hash], $this->windowIndex[$id], $this->permanentWindows[$id]);
}
}

View File

@ -36,10 +36,7 @@ namespace pocketmine {
use pocketmine\utils\VersionString;
use pocketmine\wizard\SetupWizard;
const NAME = "PocketMine-MP";
const BASE_VERSION = "3.5.10";
const IS_DEVELOPMENT_BUILD = false;
const BUILD_NUMBER = 0;
require_once __DIR__ . '/VersionInfo.php';
const MIN_PHP_VERSION = "7.2.0";
@ -177,11 +174,10 @@ namespace pocketmine {
ini_set("default_charset", "utf-8");
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"]);
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
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);
@ -190,9 +186,33 @@ namespace pocketmine {
mkdir(\pocketmine\DATA, 0777, true);
}
define('pocketmine\LOCK_FILE_PATH', \pocketmine\DATA . 'server.lock');
define('pocketmine\LOCK_FILE', fopen(\pocketmine\LOCK_FILE_PATH, "a+b"));
if(!flock(\pocketmine\LOCK_FILE, LOCK_EX | LOCK_NB)){
//wait for a shared lock to avoid race conditions if two servers started at the same time - this makes sure the
//other server wrote its PID and released exclusive lock before we get our lock
flock(\pocketmine\LOCK_FILE, LOCK_SH);
$pid = stream_get_contents(\pocketmine\LOCK_FILE);
critical_error("Another " . \pocketmine\NAME . " instance (PID $pid) is already using this folder (" . realpath(\pocketmine\DATA) . ").");
critical_error("Please stop the other server first before running a new one.");
exit(1);
}
ftruncate(\pocketmine\LOCK_FILE, 0);
fwrite(\pocketmine\LOCK_FILE, (string) getmypid());
fflush(\pocketmine\LOCK_FILE);
flock(\pocketmine\LOCK_FILE, LOCK_SH); //prevent acquiring an exclusive lock from another process, but allow reading
//Logger has a dependency on timezone
$tzError = Timezone::init();
if(isset($opts["enable-ansi"])){
Terminal::init(true);
}elseif(isset($opts["disable-ansi"])){
Terminal::init(false);
}else{
Terminal::init();
}
$logger = new MainLogger(\pocketmine\DATA . "server.log");
$logger->registerStatic();
@ -204,6 +224,9 @@ namespace pocketmine {
if(extension_loaded("xdebug")){
$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);
}
if(!extension_loaded("pocketmine_chunkutils")){
$logger->warning("ChunkUtils extension is missing. Anvil-format worlds will experience degraded performance.");
}
if(\Phar::running(true) === ""){
$logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance.");
@ -245,6 +268,8 @@ namespace pocketmine {
}
}
//TODO: move this to a Server field
define('pocketmine\START_TIME', microtime(true));
ThreadManager::init();
new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH);

View File

@ -112,7 +112,6 @@ use function array_sum;
use function asort;
use function assert;
use function base64_encode;
use function bin2hex;
use function class_exists;
use function count;
use function define;
@ -122,9 +121,7 @@ use function file_exists;
use function file_get_contents;
use function file_put_contents;
use function filemtime;
use function floor;
use function function_exists;
use function gc_collect_cycles;
use function get_class;
use function getmypid;
use function getopt;
@ -143,6 +140,7 @@ use function max;
use function microtime;
use function min;
use function mkdir;
use function ob_end_flush;
use function pcntl_signal;
use function pcntl_signal_dispatch;
use function preg_replace;
@ -295,15 +293,6 @@ class Server{
/** @var int */
public $networkCompressionLevel = 7;
/** @var bool */
private $autoTickRate = true;
/** @var int */
private $autoTickRateLimit = 20;
/** @var bool */
private $alwaysTickPlayers = false;
/** @var int */
private $baseTickRate = 1;
/** @var int */
private $autoSaveTicker = 0;
/** @var int */
@ -809,6 +798,7 @@ class Server{
* @return bool
*/
public function hasOfflinePlayerData(string $name) : bool{
$name = strtolower($name);
return file_exists($this->getDataPath() . "players/$name.dat");
}
@ -902,6 +892,11 @@ class Server{
}
/**
* Returns an online player whose name begins with or equals the given string (case insensitive).
* The closest match will be returned, or null if there are no online matches.
*
* @see Server::getPlayerExact()
*
* @param string $name
*
* @return Player|null
@ -927,6 +922,8 @@ class Server{
}
/**
* Returns an online player with the given name (case insensitive), or null if not found.
*
* @param string $name
*
* @return Player|null
@ -943,6 +940,9 @@ class Server{
}
/**
* Returns a list of online players whose names contain with the given string (case insensitive).
* If an exact match is found, only that match is returned.
*
* @param string $partialName
*
* @return Player[]
@ -1056,7 +1056,7 @@ class Server{
*/
public function unloadLevel(Level $level, bool $forceUnload = false) : bool{
if($level === $this->getDefaultLevel() and !$forceUnload){
throw new \InvalidStateException("The default level cannot be unloaded while running, please switch levels.");
throw new \InvalidStateException("The default world cannot be unloaded while running, please switch worlds.");
}
return $level->unload($forceUnload);
@ -1082,7 +1082,7 @@ class Server{
*/
public function loadLevel(string $name) : bool{
if(trim($name) === ""){
throw new LevelException("Invalid empty level name");
throw new LevelException("Invalid empty world name");
}
if($this->isLevelLoaded($name)){
return true;
@ -1101,16 +1101,24 @@ class Server{
return false;
}
/**
* @var LevelProvider $provider
* @see LevelProvider::__construct()
*/
$provider = new $providerClass($path);
try{
GeneratorManager::getGenerator($provider->getGenerator(), true);
}catch(\InvalidArgumentException $e){
$this->logger->error($this->getLanguage()->translateString("pocketmine.level.loadError", [$name, "Unknown generator \"" . $provider->getGenerator() . "\""]));
return false;
}
/** @see LevelProvider::__construct() */
$level = new Level($this, $name, new $providerClass($path));
$level = new Level($this, $name, $provider);
$this->levels[$level->getId()] = $level;
(new LevelLoadEvent($level))->call();
$level->setTickRate($this->baseTickRate);
return true;
}
@ -1142,7 +1150,7 @@ class Server{
if(($providerClass = LevelProviderManager::getProviderByName($this->getProperty("level-settings.default-format", "pmanvil"))) === null){
$providerClass = LevelProviderManager::getProviderByName("pmanvil");
if($providerClass === null){
throw new \InvalidStateException("Default level provider has not been registered");
throw new \InvalidStateException("Default world provider has not been registered");
}
}
@ -1154,8 +1162,6 @@ class Server{
$level = new Level($this, $name, new $providerClass($path));
$this->levels[$level->getId()] = $level;
$level->setTickRate($this->baseTickRate);
(new LevelInitEvent($level))->call();
(new LevelLoadEvent($level))->call();
@ -1593,11 +1599,6 @@ class Server{
}
$this->networkCompressionAsync = (bool) $this->getProperty("network.async-compression", true);
$this->autoTickRate = (bool) $this->getProperty("level-settings.auto-tick-rate", true);
$this->autoTickRateLimit = (int) $this->getProperty("level-settings.auto-tick-rate-limit", 20);
$this->alwaysTickPlayers = (bool) $this->getProperty("level-settings.always-tick-players", false);
$this->baseTickRate = (int) $this->getProperty("level-settings.base-tick-rate", 1);
$this->doTitleTick = ((bool) $this->getProperty("console.title-tick", true)) && Terminal::hasFormattingCodes();
@ -1696,12 +1697,17 @@ class Server{
Entity::init();
Tile::init();
BlockFactory::init();
BlockFactory::registerStaticRuntimeIdMappings();
Enchantment::init();
ItemFactory::init();
Item::initCreativeItems();
Biome::init();
LevelProviderManager::init();
if(extension_loaded("leveldb")){
$this->logger->debug($this->getLanguage()->translateString("pocketmine.debug.enable"));
}
GeneratorManager::registerDefaultGenerators();
$this->craftingManager = new CraftingManager();
$this->resourceManager = new ResourcePackManager($this->getDataPath() . "resource_packs" . DIRECTORY_SEPARATOR, $this->logger);
@ -1713,7 +1719,7 @@ class Server{
register_shutdown_function([$this, "crashDump"]);
$this->queryRegenerateTask = new QueryRegenerateEvent($this, 5);
$this->queryRegenerateTask = new QueryRegenerateEvent($this);
$this->pluginManager->loadPlugins($this->pluginPath);
@ -1723,13 +1729,6 @@ class Server{
$this->network->registerInterface(new RakLibInterface($this));
LevelProviderManager::init();
if(extension_loaded("leveldb")){
$this->logger->debug($this->getLanguage()->translateString("pocketmine.debug.enable"));
}
GeneratorManager::registerDefaultGenerators();
foreach((array) $this->getProperty("worlds", []) as $name => $options){
if($options === null){
$options = [];
@ -2038,7 +2037,7 @@ class Server{
}
public function reload(){
$this->logger->info("Saving levels...");
$this->logger->info("Saving worlds...");
foreach($this->levels as $level){
$level->save();
@ -2116,7 +2115,7 @@ class Server{
$player->close($player->getLeaveMessage(), $this->getProperty("settings.shutdown-message", "Server closed"));
}
$this->getLogger()->debug("Unloading all levels");
$this->getLogger()->debug("Unloading all worlds");
foreach($this->getLevels() as $level){
$this->unloadLevel($level, true);
}
@ -2148,9 +2147,6 @@ class Server{
$this->network->unregisterInterface($interface);
}
}
$this->getLogger()->debug("Collecting cycles");
gc_collect_cycles();
}catch(\Throwable $e){
$this->logger->logException($e);
$this->logger->emergency("Crashed while crashing, killing process");
@ -2221,6 +2217,7 @@ class Server{
* @param array|null $trace
*/
public function exceptionHandler(\Throwable $e, $trace = null){
while(@ob_end_flush()){}
global $lastError;
if($trace === null){
@ -2252,6 +2249,7 @@ class Server{
}
public function crashDump(){
while(@ob_end_flush()){}
if(!$this->isRunning){
return;
}
@ -2283,6 +2281,7 @@ class Server{
$p = $this->pluginManager->getPlugin($plugin);
if($p instanceof Plugin and !($p->getPluginLoader() instanceof PharPluginLoader)){
$this->logger->debug("Not sending crashdump due to caused by non-phar plugin");
$report = false;
}
}
@ -2432,8 +2431,6 @@ class Server{
foreach($this->players as $p){
if(!$p->loggedIn and ($tickTime - $p->creationTime) >= 10){
$p->close("", "Login timeout");
}elseif($this->alwaysTickPlayers and $p->spawned){
$p->onUpdate($currentTick);
}
}
@ -2443,32 +2440,13 @@ class Server{
// Level unloaded during the tick of a level earlier in this loop, perhaps by plugin
continue;
}
if($level->getTickRate() > $this->baseTickRate and --$level->tickRateCounter > 0){
continue;
}
$levelTime = microtime(true);
$level->doTick($currentTick);
$tickMs = (microtime(true) - $levelTime) * 1000;
$level->tickRateTime = $tickMs;
if($this->autoTickRate){
if($tickMs < 50 and $level->getTickRate() > $this->baseTickRate){
$level->setTickRate($r = $level->getTickRate() - 1);
if($r > $this->baseTickRate){
$level->tickRateCounter = $level->getTickRate();
}
$this->getLogger()->debug("Raising level \"{$level->getName()}\" tick rate to {$level->getTickRate()} ticks");
}elseif($tickMs >= 50){
if($level->getTickRate() === $this->baseTickRate){
$level->setTickRate(max($this->baseTickRate + 1, min($this->autoTickRateLimit, (int) floor($tickMs / 50))));
$this->getLogger()->debug(sprintf("Level \"%s\" took %gms, setting tick rate to %d ticks", $level->getName(), (int) round($tickMs, 2), $level->getTickRate()));
}elseif(($tickMs / $level->getTickRate()) >= 50 and $level->getTickRate() < $this->autoTickRateLimit){
$level->setTickRate($level->getTickRate() + 1);
$this->getLogger()->debug(sprintf("Level \"%s\" took %gms, setting tick rate to %d ticks", $level->getName(), (int) round($tickMs, 2), $level->getTickRate()));
}
$level->tickRateCounter = $level->getTickRate();
}
if($tickMs >= 50){
$this->getLogger()->debug(sprintf("World \"%s\" took too long to tick: %gms (%g ticks)", $level->getName(), $tickMs, round($tickMs / 50, 2)));
}
}
}
@ -2559,7 +2537,7 @@ class Server{
if(strlen($payload) > 2 and substr($payload, 0, 2) === "\xfe\xfd" and $this->queryHandler instanceof QueryHandler){
$this->queryHandler->handle($interface, $address, $port, $payload);
}else{
$this->logger->debug("Unhandled raw packet from $address $port: " . bin2hex($payload));
$this->logger->debug("Unhandled raw packet from $address $port: " . base64_encode($payload));
}
}catch(\Throwable $e){
$this->logger->logException($e);
@ -2608,20 +2586,19 @@ class Server{
$this->currentTPS = 20;
$this->currentUse = 0;
($this->queryRegenerateTask = new QueryRegenerateEvent($this))->call();
$this->network->updateName();
$this->network->resetStatistics();
}
if(($this->tickCounter & 0b111111111) === 0){
($this->queryRegenerateTask = new QueryRegenerateEvent($this, 5))->call();
if($this->queryHandler !== null){
$this->queryHandler->regenerateInfo();
}
}
if($this->autoSave and ++$this->autoSaveTicker >= $this->autoSaveTicks){
$this->autoSaveTicker = 0;
$this->getLogger()->debug("[Auto Save] Saving worlds...");
$start = microtime(true);
$this->doAutoSave();
$time = (microtime(true) - $start);
$this->getLogger()->debug("[Auto Save] Save completed in " . ($time >= 1 ? round($time, 3) . "s" : round($time * 1000) . "ms"));
}
if($this->sendUsageTicker > 0 and --$this->sendUsageTicker === 0){

View File

@ -0,0 +1,27 @@
<?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/
*
*
*/
namespace pocketmine;
const NAME = "PocketMine-MP";
const BASE_VERSION = "3.9.1";
const IS_DEVELOPMENT_BUILD = false;
const BUILD_NUMBER = 0;

View File

@ -36,6 +36,7 @@ use pocketmine\math\RayTraceResult;
use pocketmine\math\Vector3;
use pocketmine\metadata\Metadatable;
use pocketmine\metadata\MetadataValue;
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
use pocketmine\Player;
use pocketmine\plugin\Plugin;
use function array_merge;
@ -117,7 +118,7 @@ class Block extends Position implements BlockIds, Metadatable{
* @return int
*/
public function getRuntimeId() : int{
return BlockFactory::toStaticRuntimeId($this->getId(), $this->getDamage());
return RuntimeBlockMapping::toStaticRuntimeId($this->getId(), $this->getDamage());
}
/**

View File

@ -25,9 +25,7 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Position;
use function file_get_contents;
use function json_decode;
use function max;
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
use function min;
/**
@ -52,15 +50,6 @@ class BlockFactory{
/** @var \SplFixedArray<float> */
public static $blastResistance = null;
/** @var int[] */
public static $staticRuntimeIdMap = [];
/** @var int[] */
public static $legacyIdMap = [];
/** @var int */
private static $lastRuntimeId = 0;
/**
* Initializes the block factory. By default this is called only once on server start, however you may wish to use
* this if you need to reset the block factory back to its original defaults for whatever reason.
@ -171,7 +160,7 @@ class BlockFactory{
self::registerBlock(new Cake());
//TODO: REPEATER_BLOCK
//TODO: POWERED_REPEATER
//TODO: INVISIBLEBEDROCK
self::registerBlock(new InvisibleBedrock());
self::registerBlock(new Trapdoor());
//TODO: MONSTER_EGG
self::registerBlock(new StoneBricks());
@ -319,13 +308,13 @@ class BlockFactory{
self::registerBlock(new Stonecutter());
self::registerBlock(new GlowingObsidian());
self::registerBlock(new NetherReactor());
//TODO: INFO_UPDATE
//TODO: INFO_UPDATE2
self::registerBlock(new InfoUpdate(Block::INFO_UPDATE, 0, "update!"));
self::registerBlock(new InfoUpdate(Block::INFO_UPDATE2, 0, "ate!upd"));
//TODO: MOVINGBLOCK
//TODO: OBSERVER
//TODO: STRUCTURE_BLOCK
//TODO: RESERVED6
self::registerBlock(new Reserved6(Block::RESERVED6, 0, "reserved6"));
for($id = 0, $size = self::$fullList->getSize() >> 4; $id < $size; ++$id){
if(self::$fullList[$id << 4] === null){
@ -427,16 +416,9 @@ class BlockFactory{
return $b !== null and !($b instanceof UnknownBlock);
}
public static function registerStaticRuntimeIdMappings() : void{
/** @var mixed[] $runtimeIdMap */
$runtimeIdMap = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "runtimeid_table.json"), true);
foreach($runtimeIdMap as $k => $obj){
self::registerMapping($k, $obj["id"], $obj["data"]);
}
}
/**
* @internal
* @deprecated
*
* @param int $id
* @param int $meta
@ -444,15 +426,11 @@ class BlockFactory{
* @return int
*/
public static function toStaticRuntimeId(int $id, int $meta = 0) : int{
/*
* try id+meta first
* if not found, try id+0 (strip meta)
* if still not found, return update! block
*/
return self::$staticRuntimeIdMap[($id << 4) | $meta] ?? self::$staticRuntimeIdMap[$id << 4] ?? self::$staticRuntimeIdMap[BlockIds::INFO_UPDATE << 4];
return RuntimeBlockMapping::toStaticRuntimeId($id, $meta);
}
/**
* @deprecated
* @internal
*
* @param int $runtimeId
@ -460,13 +438,6 @@ class BlockFactory{
* @return int[] [id, meta]
*/
public static function fromStaticRuntimeId(int $runtimeId) : array{
$v = self::$legacyIdMap[$runtimeId];
return [$v >> 4, $v & 0xf];
}
private static function registerMapping(int $staticRuntimeId, int $legacyId, int $legacyMeta) : void{
self::$staticRuntimeIdMap[($legacyId << 4) | $legacyMeta] = $staticRuntimeId;
self::$legacyIdMap[$staticRuntimeId] = ($legacyId << 4) | $legacyMeta;
self::$lastRuntimeId = max(self::$lastRuntimeId, $staticRuntimeId);
return RuntimeBlockMapping::fromStaticRuntimeId($runtimeId);
}
}

View File

@ -46,7 +46,7 @@ class Carpet extends Flowable{
}
public function getName() : string{
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Carpet";
return ColorBlockMetaHelper::getColorFromMeta($this->getVariant()) . " Carpet";
}
protected function recalculateBoundingBox() : ?AxisAlignedBB{

View File

@ -30,6 +30,18 @@ use pocketmine\math\Vector3;
class CobblestoneWall extends Transparent{
public const NONE_MOSSY_WALL = 0;
public const MOSSY_WALL = 1;
public const GRANITE_WALL = 2;
public const DIORITE_WALL = 3;
public const ANDESITE_WALL = 4;
public const SANDSTONE_WALL = 5;
public const BRICK_WALL = 6;
public const STONE_BRICK_WALL = 7;
public const MOSSY_STONE_BRICK_WALL = 8;
public const NETHER_BRICK_WALL = 9;
public const END_STONE_BRICK_WALL = 10;
public const PRISMARINE_WALL = 11;
public const RED_SANDSTONE_WALL = 12;
public const RED_NETHER_BRICK_WALL = 13;
protected $id = self::COBBLESTONE_WALL;
@ -50,11 +62,23 @@ class CobblestoneWall extends Transparent{
}
public function getName() : string{
if($this->meta === 0x01){
return "Mossy Cobblestone Wall";
}
return "Cobblestone Wall";
static $names = [
self::NONE_MOSSY_WALL => "Cobblestone",
self::MOSSY_WALL => "Mossy Cobblestone",
self::GRANITE_WALL => "Granite",
self::DIORITE_WALL => "Diorite",
self::ANDESITE_WALL => "Andesite",
self::SANDSTONE_WALL => "Sandstone",
self::BRICK_WALL => "Brick",
self::STONE_BRICK_WALL => "Stone Brick",
self::MOSSY_STONE_BRICK_WALL => "Mossy Stone Brick",
self::NETHER_BRICK_WALL => "Nether Brick",
self::END_STONE_BRICK_WALL => "End Stone Brick",
self::PRISMARINE_WALL => "Prismarine",
self::RED_SANDSTONE_WALL => "Red Sandstone",
self::RED_NETHER_BRICK_WALL => "Red Nether Brick"
];
return ($names[$this->getVariant()] ?? "Unknown") . " Wall";
}
protected function recalculateBoundingBox() : ?AxisAlignedBB{

View File

@ -35,7 +35,7 @@ class Concrete extends Solid{
}
public function getName() : string{
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Concrete";
return ColorBlockMetaHelper::getColorFromMeta($this->getVariant()) . " Concrete";
}
public function getHardness() : float{

View File

@ -34,7 +34,7 @@ class ConcretePowder extends Fallable{
}
public function getName() : string{
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Concrete Powder";
return ColorBlockMetaHelper::getColorFromMeta($this->getVariant()) . " Concrete Powder";
}
public function getHardness() : float{

View File

@ -39,7 +39,7 @@ class DoublePlant extends Flowable{
}
public function canBeReplaced() : bool{
return $this->meta === 2 or $this->meta === 3; //grass or fern
return $this->getVariant() === 2 or $this->getVariant() === 3; //grass or fern
}
public function getName() : string{
@ -95,11 +95,11 @@ class DoublePlant extends Flowable{
}
public function getToolType() : int{
return ($this->meta === 2 or $this->meta === 3) ? BlockToolType::TYPE_SHEARS : BlockToolType::TYPE_NONE;
return ($this->getVariant() === 2 or $this->getVariant() === 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
return ($this->getVariant() === 2 or $this->getVariant() === 3) ? 1 : 0; //only grass or fern require shears
}
public function getDrops(Item $item) : array{

View File

@ -56,7 +56,7 @@ class Flower extends Flowable{
self::TYPE_PINK_TULIP => "Pink Tulip",
self::TYPE_OXEYE_DAISY => "Oxeye Daisy"
];
return $names[$this->meta] ?? "Unknown";
return $names[$this->getVariant()] ?? "Unknown";
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{

View File

@ -0,0 +1,31 @@
<?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 InfoUpdate extends Solid{
public function getHardness() : float{
return 1;
}
}

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;
class InvisibleBedrock extends Transparent{
protected $id = self::INVISIBLE_BEDROCK;
public function __construct(){
}
public function getName() : string{
return "Invisible Bedrock";
}
public function getHardness() : float{
return -1;
}
public function getBlastResistance() : float{
return 18000000;
}
public function isBreakable(Item $item) : bool{
return false;
}
}

View File

@ -44,4 +44,8 @@ class IronTrapdoor extends Trapdoor{
public function getToolHarvestLevel() : int{
return TieredTool::TIER_WOODEN;
}
public function getFuelTime() : int{
return 0; //TODO: remove this hack on 4.0
}
}

View File

@ -112,4 +112,8 @@ class ItemFrame extends Flowable{
public function isAffectedBySilkTouch() : bool{
return false;
}
public function getHardness() : float{
return 0.25;
}
}

View File

@ -58,8 +58,10 @@ class Ladder extends Transparent{
}
public function onEntityCollide(Entity $entity) : void{
$entity->resetFallDistance();
$entity->onGround = true;
if($entity->asVector3()->floor()->distanceSquared($this) < 1){ //entity coordinates must be inside block
$entity->resetFallDistance();
$entity->onGround = true;
}
}
protected function recalculateBoundingBox() : ?AxisAlignedBB{

View File

@ -188,7 +188,7 @@ class Leaves extends Transparent{
}
public function canDropApples() : bool{
return $this->meta === self::OAK;
return $this->getVariant() === self::OAK;
}
public function getFlameEncouragement() : int{

View File

@ -44,6 +44,6 @@ class Leaves2 extends Leaves{
}
public function canDropApples() : bool{
return $this->meta === self::DARK_OAK;
return $this->getVariant() === self::DARK_OAK;
}
}

View File

@ -32,6 +32,7 @@ use pocketmine\level\sound\FizzSound;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Vector3;
use function array_fill;
use function intdiv;
use function lcg_value;
use function min;
@ -372,7 +373,7 @@ abstract class Liquid extends Transparent{
*/
private function getOptimalFlowDirections() : array{
$flowCost = array_fill(0, 4, 1000);
$maxCost = 4 / $this->getFlowDecayPerBlock();
$maxCost = intdiv(4, $this->getFlowDecayPerBlock());
for($j = 0; $j < 4; ++$j){
$x = $this->x;
$y = $this->y;

View File

@ -46,4 +46,6 @@ class NoteBlock extends Solid{
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;
class PackedIce extends Solid{
protected $id = self::PACKED_ICE;
@ -46,4 +48,8 @@ class PackedIce extends Solid{
public function getToolType() : int{
return BlockToolType::TYPE_PICKAXE;
}
public function getDropsForCompatibleTool(Item $item) : array{
return [];
}
}

View File

@ -55,7 +55,7 @@ class Quartz extends Solid{
}
public function place(Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, Player $player = null) : bool{
if($this->meta !== self::NORMAL){
if($this->getVariant() !== self::NORMAL){
$this->meta = PillarRotationHelper::getMetaFromFace($this->meta, $face);
}
return $this->getLevel()->setBlock($blockReplace, $this, true, true);

View File

@ -0,0 +1,31 @@
<?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 Reserved6 extends Solid{
public function getHardness() : float{
return 0;
}
}

View File

@ -40,7 +40,7 @@ class Sand extends Fallable{
}
public function getName() : string{
if($this->meta === 0x01){
if($this->getVariant() === 0x01){
return "Red Sand";
}

View File

@ -78,7 +78,7 @@ abstract class Slab extends Transparent{
}
}else{ //TODO: collision
if($blockReplace->getId() === $this->id){
if($blockReplace->getVariant() === $this->meta){
if($blockReplace->getVariant() === $this->getVariant()){
$this->getLevel()->setBlock($blockReplace, BlockFactory::get($this->getDoubleSlabId(), $this->getVariant()), true);
return true;

View File

@ -30,6 +30,6 @@ class StainedClay extends HardenedClay{
protected $id = self::STAINED_CLAY;
public function getName() : string{
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Stained Clay";
return ColorBlockMetaHelper::getColorFromMeta($this->getVariant()) . " Stained Clay";
}
}

View File

@ -30,6 +30,6 @@ class StainedGlass extends Glass{
protected $id = self::STAINED_GLASS;
public function getName() : string{
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Stained Glass";
return ColorBlockMetaHelper::getColorFromMeta($this->getVariant()) . " Stained Glass";
}
}

View File

@ -30,6 +30,6 @@ class StainedGlassPane extends GlassPane{
protected $id = self::STAINED_GLASS_PANE;
public function getName() : string{
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Stained Glass Pane";
return ColorBlockMetaHelper::getColorFromMeta($this->getVariant()) . " Stained Glass Pane";
}
}

View File

@ -26,6 +26,12 @@ namespace pocketmine\block;
class StoneSlab2 extends StoneSlab{
public const TYPE_RED_SANDSTONE = 0;
public const TYPE_PURPUR = 1;
public const TYPE_PRISMARINE = 2;
public const TYPE_DARK_PRISMARINE = 3;
public const TYPE_PRISMARINE_BRICKS = 4;
public const TYPE_MOSSY_COBBLESTONE = 5;
public const TYPE_SMOOTH_SANDSTONE = 6;
public const TYPE_RED_NETHER_BRICK = 7;
protected $id = self::STONE_SLAB2;
@ -36,7 +42,13 @@ class StoneSlab2 extends StoneSlab{
public function getName() : string{
static $names = [
self::TYPE_RED_SANDSTONE => "Red Sandstone",
self::TYPE_PURPUR => "Purpur"
self::TYPE_PURPUR => "Purpur",
self::TYPE_PRISMARINE => "Prismarine",
self::TYPE_DARK_PRISMARINE => "Dark Prismarine",
self::TYPE_PRISMARINE_BRICKS => "Prismarine Bricks",
self::TYPE_MOSSY_COBBLESTONE => "Mossy Cobblestone",
self::TYPE_SMOOTH_SANDSTONE => "Smooth Sandstone",
self::TYPE_RED_NETHER_BRICK => "Red Nether Brick"
];
return (($this->meta & 0x08) > 0 ? "Upper " : "") . ($names[$this->getVariant()] ?? "") . " Slab";

View File

@ -37,6 +37,10 @@ class Stonecutter extends Solid{
return "Stonecutter";
}
public function getHardness() : float{
return 3.5;
}
public function getToolType() : int{
return BlockToolType::TYPE_PICKAXE;
}

View File

@ -25,6 +25,8 @@ namespace pocketmine\block;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Arrow;
use pocketmine\item\Durable;
use pocketmine\item\enchantment\Enchantment;
use pocketmine\item\FlintSteel;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
@ -51,8 +53,10 @@ class TNT extends Solid{
}
public function onActivate(Item $item, Player $player = null) : bool{
if($item instanceof FlintSteel){
$item->applyDamage(1);
if($item instanceof FlintSteel or $item->hasEnchantment(Enchantment::FIRE_ASPECT)){
if($item instanceof Durable){
$item->applyDamage(1);
}
$this->ignite();
return true;
}

View File

@ -43,7 +43,7 @@ class Wool extends Solid{
}
public function getName() : string{
return ColorBlockMetaHelper::getColorFromMeta($this->meta) . " Wool";
return ColorBlockMetaHelper::getColorFromMeta($this->getVariant()) . " Wool";
}
public function getBreakTime(Item $item) : float{

View File

@ -26,6 +26,7 @@ declare(strict_types=1);
*/
namespace pocketmine\command;
use pocketmine\command\utils\CommandException;
use pocketmine\lang\TextContainer;
use pocketmine\lang\TranslationContainer;
use pocketmine\permission\PermissionManager;
@ -92,6 +93,7 @@ abstract class Command{
* @param string[] $args
*
* @return mixed
* @throws CommandException
*/
abstract public function execute(CommandSender $sender, string $commandLabel, array $args);

View File

@ -66,13 +66,13 @@ use pocketmine\command\defaults\VersionCommand;
use pocketmine\command\defaults\WhitelistCommand;
use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\Server;
use function array_map;
use function array_shift;
use function count;
use function explode;
use function implode;
use function min;
use function str_getcsv;
use function preg_match_all;
use function stripslashes;
use function strpos;
use function strtolower;
use function trim;
@ -247,7 +247,16 @@ class SimpleCommandMap implements CommandMap{
}
public function dispatch(CommandSender $sender, string $commandLine) : bool{
$args = array_map("\stripslashes", str_getcsv($commandLine, " "));
$args = [];
preg_match_all('/"((?:\\\\.|[^\\\\"])*)"|(\S+)/u', $commandLine, $matches);
foreach($matches[0] as $k => $_){
for($i = 1; $i <= 2; ++$i){
if($matches[$i][$k] !== ""){
$args[$k] = stripslashes($matches[$i][$k]);
break;
}
}
}
$sentCommandLabel = "";
$target = $this->matchCommand($sentCommandLabel, $args);

View File

@ -53,6 +53,9 @@ class DeopCommand extends VanillaCommand{
}
$name = array_shift($args);
if(!Player::isValidUserName($name)){
throw new InvalidCommandSyntaxException();
}
$player = $sender->getServer()->getOfflinePlayer($name);
$player->setOp(false);

View File

@ -83,7 +83,7 @@ class EffectCommand extends VanillaCommand{
$amplification = 0;
if(count($args) >= 3){
if(($d = $this->getBoundedInt($sender, $args[2], 0, INT32_MAX)) === null){
if(($d = $this->getBoundedInt($sender, $args[2], 0, (int) (INT32_MAX / 20))) === null){
return false;
}
$duration = $d * 20; //ticks

View File

@ -55,7 +55,7 @@ class KillCommand extends VanillaCommand{
if(count($args) === 1){
if(!$sender->hasPermission("pocketmine.command.kill.other")){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.permission"));
$sender->sendMessage($sender->getServer()->getLanguage()->translateString(TextFormat::RED . "%commands.generic.permission"));
return true;
}
@ -74,7 +74,7 @@ class KillCommand extends VanillaCommand{
if($sender instanceof Player){
if(!$sender->hasPermission("pocketmine.command.kill.self")){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.permission"));
$sender->sendMessage($sender->getServer()->getLanguage()->translateString(TextFormat::RED . "%commands.generic.permission"));
return true;
}

View File

@ -53,6 +53,9 @@ class OpCommand extends VanillaCommand{
}
$name = array_shift($args);
if(!Player::isValidUserName($name)){
throw new InvalidCommandSyntaxException();
}
$player = $sender->getServer()->getOfflinePlayer($name);
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.op.success", [$player->getName()]));

View File

@ -26,6 +26,8 @@ namespace pocketmine\command\defaults;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\lang\TranslationContainer;
use function microtime;
use function round;
class SaveCommand extends VanillaCommand{
@ -43,7 +45,8 @@ class SaveCommand extends VanillaCommand{
return true;
}
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.save.start"));
Command::broadcastCommandMessage($sender, new TranslationContainer("pocketmine.save.start"));
$start = microtime(true);
foreach($sender->getServer()->getOnlinePlayers() as $player){
$player->save();
@ -53,7 +56,7 @@ class SaveCommand extends VanillaCommand{
$level->save(true);
}
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.save.success"));
Command::broadcastCommandMessage($sender, new TranslationContainer("pocketmine.save.success", [round(microtime(true) - $start, 3)]));
return true;
}

View File

@ -108,13 +108,11 @@ class StatusCommand extends VanillaCommand{
foreach($server->getLevels() as $level){
$levelName = $level->getFolderName() !== $level->getName() ? " (" . $level->getName() . ")" : "";
$timeColor = ($level->getTickRate() > 1 or $level->getTickRateTime() > 40) ? TextFormat::RED : TextFormat::YELLOW;
$tickRate = $level->getTickRate() > 1 ? " (tick rate " . $level->getTickRate() . ")" : "";
$timeColor = $level->getTickRateTime() > 40 ? TextFormat::RED : TextFormat::YELLOW;
$sender->sendMessage(TextFormat::GOLD . "World \"{$level->getFolderName()}\"$levelName: " .
TextFormat::RED . number_format(count($level->getChunks())) . TextFormat::GREEN . " chunks, " .
TextFormat::RED . number_format(count($level->getEntities())) . TextFormat::GREEN . " entities, " .
TextFormat::RED . number_format(count($level->getTiles())) . TextFormat::GREEN . " tiles. " .
"Time $timeColor" . round($level->getTickRateTime(), 2) . "ms" . $tickRate
TextFormat::RED . number_format(count($level->getEntities())) . TextFormat::GREEN . " entities. " .
"Time $timeColor" . round($level->getTickRateTime(), 2) . "ms"
);
}

View File

@ -50,7 +50,7 @@ class TimeCommand extends VanillaCommand{
if($args[0] === "start"){
if(!$sender->hasPermission("pocketmine.command.time.start")){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.permission"));
$sender->sendMessage($sender->getServer()->getLanguage()->translateString(TextFormat::RED . "%commands.generic.permission"));
return true;
}
@ -61,7 +61,7 @@ class TimeCommand extends VanillaCommand{
return true;
}elseif($args[0] === "stop"){
if(!$sender->hasPermission("pocketmine.command.time.stop")){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.permission"));
$sender->sendMessage($sender->getServer()->getLanguage()->translateString(TextFormat::RED . "%commands.generic.permission"));
return true;
}
@ -72,7 +72,7 @@ class TimeCommand extends VanillaCommand{
return true;
}elseif($args[0] === "query"){
if(!$sender->hasPermission("pocketmine.command.time.query")){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.permission"));
$sender->sendMessage($sender->getServer()->getLanguage()->translateString(TextFormat::RED . "%commands.generic.permission"));
return true;
}
@ -81,7 +81,7 @@ class TimeCommand extends VanillaCommand{
}else{
$level = $sender->getServer()->getDefaultLevel();
}
$sender->sendMessage(new TranslationContainer("commands.time.query", [$level->getTime()]));
$sender->sendMessage($sender->getServer()->getLanguage()->translateString("commands.time.query", [$level->getTime()]));
return true;
}
@ -92,7 +92,7 @@ class TimeCommand extends VanillaCommand{
if($args[0] === "set"){
if(!$sender->hasPermission("pocketmine.command.time.set")){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.permission"));
$sender->sendMessage($sender->getServer()->getLanguage()->translateString(TextFormat::RED . "%commands.generic.permission"));
return true;
}
@ -111,7 +111,7 @@ class TimeCommand extends VanillaCommand{
Command::broadcastCommandMessage($sender, new TranslationContainer("commands.time.set", [$value]));
}elseif($args[0] === "add"){
if(!$sender->hasPermission("pocketmine.command.time.add")){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.permission"));
$sender->sendMessage($sender->getServer()->getLanguage()->translateString(TextFormat::RED . "%commands.generic.permission"));
return true;
}

View File

@ -27,6 +27,7 @@ use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\lang\TranslationContainer;
use pocketmine\Player;
use pocketmine\utils\TextFormat;
use function count;
use function implode;
@ -94,6 +95,9 @@ class WhitelistCommand extends VanillaCommand{
if($this->badPerm($sender, strtolower($args[0]))){
return false;
}
if(!Player::isValidUserName($args[1])){
throw new InvalidCommandSyntaxException();
}
switch(strtolower($args[0])){
case "add":
$sender->getServer()->getOfflinePlayer($args[1])->setWhitelisted(true);
@ -111,9 +115,13 @@ class WhitelistCommand extends VanillaCommand{
return true;
}
private function badPerm(CommandSender $sender, string $perm) : bool{
if(!$sender->hasPermission("pocketmine.command.whitelist.$perm")){
$sender->sendMessage(new TranslationContainer(TextFormat::RED . "%commands.generic.permission"));
private function badPerm(CommandSender $sender, string $subcommand) : bool{
static $map = [
"on" => "enable",
"off" => "disable"
];
if(!$sender->hasPermission("pocketmine.command.whitelist." . ($map[$subcommand] ?? $subcommand))){
$sender->sendMessage($sender->getServer()->getLanguage()->translateString(TextFormat::RED . "%commands.generic.permission"));
return true;
}

View File

@ -40,6 +40,11 @@ class Attribute{
public const ATTACK_DAMAGE = 8;
public const EXPERIENCE_LEVEL = 9;
public const EXPERIENCE = 10;
public const UNDERWATER_MOVEMENT = 11;
public const LUCK = 12;
public const FALL_DAMAGE = 13;
public const HORSE_JUMP_STRENGTH = 14;
public const ZOMBIE_SPAWN_REINFORCEMENTS = 15;
private $id;
protected $minValue;
@ -66,8 +71,11 @@ class Attribute{
self::addAttribute(self::ATTACK_DAMAGE, "minecraft:attack_damage", 0.00, 340282346638528859811704183484516925440.00, 1.00, false);
self::addAttribute(self::EXPERIENCE_LEVEL, "minecraft:player.level", 0.00, 24791.00, 0.00);
self::addAttribute(self::EXPERIENCE, "minecraft:player.experience", 0.00, 1.00, 0.00);
//TODO: minecraft:luck (for fishing?)
//TODO: minecraft:fall_damage
self::addAttribute(self::UNDERWATER_MOVEMENT, "minecraft:underwater_movement", 0.0, 340282346638528859811704183484516925440.0, 0.02);
self::addAttribute(self::LUCK, "minecraft:luck", -1024.0, 1024.0, 0.0);
self::addAttribute(self::FALL_DAMAGE, "minecraft:fall_damage", 0.0, 340282346638528859811704183484516925440.0, 1.0);
self::addAttribute(self::HORSE_JUMP_STRENGTH, "minecraft:horse.jump_strength", 0.0, 2.0, 0.7);
self::addAttribute(self::ZOMBIE_SPAWN_REINFORCEMENTS, "minecraft:zombie.spawn_reinforcements", 0.0, 1.0, 0.0);
}
/**

View File

@ -62,12 +62,12 @@ use pocketmine\nbt\tag\DoubleTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\protocol\AddEntityPacket;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\MoveEntityAbsolutePacket;
use pocketmine\network\mcpe\protocol\RemoveEntityPacket;
use pocketmine\network\mcpe\protocol\SetEntityDataPacket;
use pocketmine\network\mcpe\protocol\SetEntityMotionPacket;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\AddActorPacket;
use pocketmine\network\mcpe\protocol\MoveActorAbsolutePacket;
use pocketmine\network\mcpe\protocol\RemoveActorPacket;
use pocketmine\network\mcpe\protocol\SetActorDataPacket;
use pocketmine\network\mcpe\protocol\SetActorMotionPacket;
use pocketmine\Player;
use pocketmine\plugin\Plugin;
use pocketmine\Server;
@ -107,6 +107,10 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
public const DATA_TYPE_LONG = 7;
public const DATA_TYPE_VECTOR3F = 8;
/*
* Readers beware: this isn't a nice list. Some of the properties have different types for different entities, and
* are used for entirely different things.
*/
public const DATA_FLAGS = 0;
public const DATA_HEALTH = 1; //int (minecart/boat)
public const DATA_VARIANT = 2; //int
@ -124,17 +128,21 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
public const DATA_PADDLE_TIME_RIGHT = 14; //float
public const DATA_EXPERIENCE_VALUE = 15; //int (xp orb)
public const DATA_MINECART_DISPLAY_BLOCK = 16; //int (id | (data << 16))
public const DATA_HORSE_FLAGS = 16; //int
/* 16 (byte) used by wither skull */
public const DATA_MINECART_DISPLAY_OFFSET = 17; //int
public const DATA_SHOOTER_ID = 17; //long (used by arrows)
public const DATA_MINECART_HAS_DISPLAY = 18; //byte (must be 1 for minecart to show block inside)
//TODO: add more properties
public const DATA_HORSE_TYPE = 19; //byte
/* 20 (unknown)
* 21 (unknown) */
public const DATA_CHARGE_AMOUNT = 22; //int8, used for ghasts and also crossbow charging
public const DATA_ENDERMAN_HELD_ITEM_ID = 23; //short
public const DATA_ENTITY_AGE = 24; //short
/* 26 (byte) player-specific flags
* 27 (int) player "index"?
* 28 (block coords) bed position */
/* 25 (int) used by horse, (byte) used by witch */
public const DATA_PLAYER_FLAGS = 26; //byte
public const DATA_PLAYER_INDEX = 27; //int, used for marker colours and agent nametag colours
public const DATA_PLAYER_BED_POSITION = 28; //blockpos
public const DATA_FIREBALL_POWER_X = 29; //float
public const DATA_FIREBALL_POWER_Y = 30;
public const DATA_FIREBALL_POWER_Z = 31;
@ -145,9 +153,9 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
public const DATA_POTION_AUX_VALUE = 36; //short
public const DATA_LEAD_HOLDER_EID = 37; //long
public const DATA_SCALE = 38; //float
public const DATA_INTERACTIVE_TAG = 39; //string (button text)
public const DATA_NPC_SKIN_ID = 40; //string
public const DATA_URL_TAG = 41; //string
public const DATA_HAS_NPC_COMPONENT = 39; //byte (???)
public const DATA_NPC_SKIN_INDEX = 40; //string
public const DATA_NPC_ACTIONS = 41; //string (maybe JSON blob?)
public const DATA_MAX_AIR = 42; //short
public const DATA_MARK_VARIANT = 43; //int
public const DATA_CONTAINER_TYPE = 44; //byte (ContainerComponent)
@ -195,12 +203,27 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
public const DATA_BOAT_BUBBLE_TIME = 86; //int (time in bubble column)
public const DATA_PLAYER_AGENT_EID = 87; //long
/* 88 (float) related to panda sitting
* 89 (float) related to panda sitting
* 90 (unknown) */
* 89 (float) related to panda sitting */
public const DATA_EAT_COUNTER = 90; //int (used by pandas)
public const DATA_FLAGS2 = 91; //long (extended data flags)
/* 92 (float) related to panda lying down
* 93 (float) related to panda lying down */
public const DATA_AREA_EFFECT_CLOUD_DURATION = 94; //int
public const DATA_AREA_EFFECT_CLOUD_SPAWN_TIME = 95; //int
public const DATA_AREA_EFFECT_CLOUD_RADIUS_PER_TICK = 96; //float, usually negative
public const DATA_AREA_EFFECT_CLOUD_RADIUS_CHANGE_ON_PICKUP = 97; //float
public const DATA_AREA_EFFECT_CLOUD_PICKUP_COUNT = 98; //int
public const DATA_INTERACTIVE_TAG = 99; //string (button text)
public const DATA_TRADE_TIER = 100; //int
public const DATA_MAX_TRADE_TIER = 101; //int
public const DATA_TRADE_XP = 102; //int
public const DATA_SKIN_ID = 103; //int ???
/* 104 (int) related to wither */
public const DATA_COMMAND_BLOCK_TICK_DELAY = 105; //int
public const DATA_COMMAND_BLOCK_EXECUTE_ON_FIRST_TICK = 106; //byte
public const DATA_AMBIENT_SOUND_INTERVAL_MIN = 107; //float
public const DATA_AMBIENT_SOUND_INTERVAL_RANGE = 108; //float
public const DATA_AMBIENT_SOUND_EVENT = 109; //string
public const DATA_FLAG_ONFIRE = 0;
public const DATA_FLAG_SNEAKING = 1;
@ -273,6 +296,26 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
public const DATA_FLAG_IN_SCAFFOLDING = 68;
public const DATA_FLAG_OVER_SCAFFOLDING = 69;
public const DATA_FLAG_FALL_THROUGH_SCAFFOLDING = 70;
public const DATA_FLAG_BLOCKING = 71; //shield
public const DATA_FLAG_DISABLE_BLOCKING = 72;
//73 is set when a player is attacked while using shield, unclear on purpose
//74 related to shield usage, needs further investigation
public const DATA_FLAG_SLEEPING = 75;
//76 related to sleeping, unclear usage
public const DATA_FLAG_TRADE_INTEREST = 77;
public const DATA_FLAG_DOOR_BREAKER = 78; //...
public const DATA_FLAG_BREAKING_OBSTRUCTION = 79;
public const DATA_FLAG_DOOR_OPENER = 80; //...
public const DATA_FLAG_ILLAGER_CAPTAIN = 81;
public const DATA_FLAG_STUNNED = 82;
public const DATA_FLAG_ROARING = 83;
public const DATA_FLAG_DELAYED_ATTACKING = 84;
public const DATA_FLAG_AVOIDING_MOBS = 85;
//86 used by RangedAttackGoal
//87 used by NearestAttackableTargetGoal
public const DATA_PLAYER_FLAG_SLEEP = 1;
public const DATA_PLAYER_FLAG_DEAD = 2; //TODO: CHECK
public static $entityCount = 1;
/** @var Entity[] */
@ -525,6 +568,8 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
/** @var bool */
protected $constructed = false;
/** @var bool */
private $closeInFlight = false;
public function __construct(Level $level, CompoundTag $nbt){
$this->constructed = true;
@ -556,6 +601,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
throw new \InvalidStateException("Cannot create entities in unloaded chunks");
}
$this->motion = new Vector3(0, 0, 0);
if($this->namedtag->hasTag("Motion", ListTag::class)){
/** @var float[] $motion */
$motion = $this->namedtag->getListTag("Motion")->getAllValues();
@ -622,7 +668,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
* @return bool
*/
public function isNameTagAlwaysVisible() : bool{
return $this->getGenericFlag(self::DATA_FLAG_ALWAYS_SHOW_NAMETAG);
return $this->propertyManager->getByte(self::DATA_ALWAYS_SHOW_NAMETAG) === 1;
}
@ -1097,7 +1143,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$this->setFireTicks($ticks);
}
$this->setGenericFlag(self::DATA_FLAG_ONFIRE, true);
$this->setGenericFlag(self::DATA_FLAG_ONFIRE, $this->isOnFire());
}
/**
@ -1164,6 +1210,9 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
protected function updateMovement(bool $teleport = false) : void{
//TODO: hack for client-side AI interference: prevent client sided movement when motion is 0
$this->setImmobile($this->motion->x == 0 and $this->motion->y == 0 and $this->motion->z == 0);
$diffPosition = ($this->x - $this->lastX) ** 2 + ($this->y - $this->lastY) ** 2 + ($this->z - $this->lastZ) ** 2;
$diffRotation = ($this->yaw - $this->lastYaw) ** 2 + ($this->pitch - $this->lastPitch) ** 2;
@ -1192,7 +1241,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
protected function broadcastMovement(bool $teleport = false) : void{
$pk = new MoveEntityAbsolutePacket();
$pk = new MoveActorAbsolutePacket();
$pk->entityRuntimeId = $this->id;
$pk->position = $this->getOffsetPosition($this);
@ -1204,14 +1253,14 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$pk->zRot = $this->yaw;
if($teleport){
$pk->flags |= MoveEntityAbsolutePacket::FLAG_TELEPORT;
$pk->flags |= MoveActorAbsolutePacket::FLAG_TELEPORT;
}
$this->level->broadcastPacketToViewers($this, $pk);
}
protected function broadcastMotion() : void{
$pk = new SetEntityMotionPacket();
$pk = new SetActorMotionPacket();
$pk->entityRuntimeId = $this->id;
$pk->motion = $this->getMotion();
@ -1632,7 +1681,8 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
assert(abs($dx) <= 20 and abs($dy) <= 20 and abs($dz) <= 20, "Movement distance is excessive: dx=$dx, dy=$dy, dz=$dz");
$list = $this->level->getCollisionCubes($this, $this->level->getTickRate() > 1 ? $this->boundingBox->offsetCopy($dx, $dy, $dz) : $this->boundingBox->addCoord($dx, $dy, $dz), false);
//TODO: bad hack here will cause unexpected behaviour under heavy lag
$list = $this->level->getCollisionCubes($this, $this->level->getTickRateTime() > 50 ? $this->boundingBox->offsetCopy($dx, $dy, $dz) : $this->boundingBox->addCoord($dx, $dy, $dz), false);
foreach($list as $bb){
$dy = $bb->calculateYOffset($this->boundingBox, $dy);
@ -1977,7 +2027,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
* @param Player $player
*/
protected function sendSpawnPacket(Player $player) : void{
$pk = new AddEntityPacket();
$pk = new AddActorPacket();
$pk->entityRuntimeId = $this->getId();
$pk->type = static::NETWORK_ID;
$pk->position = $this->asVector3();
@ -2027,7 +2077,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
public function despawnFrom(Player $player, bool $send = true) : void{
if(isset($this->hasSpawned[$player->getLoaderId()])){
if($send){
$pk = new RemoveEntityPacket();
$pk = new RemoveActorPacket();
$pk->entityUniqueId = $this->id;
$player->dataPacket($pk);
}
@ -2067,7 +2117,12 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
* WARNING: Entities are unusable after this has been executed!
*/
public function close() : void{
if($this->closeInFlight){
return;
}
if(!$this->closed){
$this->closeInFlight = true;
(new EntityDespawnEvent($this))->call();
$this->closed = true;
@ -2086,6 +2141,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$this->namedtag = null;
$this->lastDamageCause = null;
$this->closeInFlight = false;
}
}
@ -2143,7 +2199,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
$player = [$player];
}
$pk = new SetEntityDataPacket();
$pk = new SetActorDataPacket();
$pk->entityRuntimeId = $this->getId();
$pk->metadata = $data ?? $this->propertyManager->getAll();
@ -2160,7 +2216,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{
}
public function broadcastEntityEvent(int $eventId, ?int $eventData = null, ?array $players = null) : void{
$pk = new EntityEventPacket();
$pk = new ActorEventPacket();
$pk->entityRuntimeId = $this->id;
$pk->event = $eventId;
$pk->data = $eventData ?? 0;

View File

@ -46,8 +46,8 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\AddPlayerPacket;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\LevelEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\PlayerListPacket;
@ -60,6 +60,7 @@ use function array_merge;
use function array_rand;
use function array_values;
use function ceil;
use function in_array;
use function max;
use function min;
use function mt_rand;
@ -70,13 +71,6 @@ use const INT32_MIN;
class Human extends Creature implements ProjectileSource, InventoryHolder{
public const DATA_PLAYER_FLAG_SLEEP = 1;
public const DATA_PLAYER_FLAG_DEAD = 2; //TODO: CHECK
public const DATA_PLAYER_FLAGS = 26;
public const DATA_PLAYER_BED_POSITION = 28;
/** @var PlayerInventory */
protected $inventory;
@ -105,18 +99,36 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
public function __construct(Level $level, CompoundTag $nbt){
if($this->skin === null){
$skinTag = $nbt->getCompoundTag("Skin");
if($skinTag === null or !self::isValidSkin($skinTag->hasTag("Data", ByteArrayTag::class) ?
$skinTag->getByteArray("Data") :
$skinTag->getString("Data", "")
)){
if($skinTag === null){
throw new \InvalidStateException((new \ReflectionClass($this))->getShortName() . " must have a valid skin set");
}
$this->skin = self::deserializeSkinNBT($skinTag); //this throws if the skin is invalid
}
parent::__construct($level, $nbt);
}
/**
* @param CompoundTag $skinTag
*
* @return Skin
* @throws \InvalidArgumentException
*/
protected static function deserializeSkinNBT(CompoundTag $skinTag) : Skin{
$skin = new Skin(
$skinTag->getString("Name"),
$skinTag->hasTag("Data", StringTag::class) ? $skinTag->getString("Data") : $skinTag->getByteArray("Data"), //old data (this used to be saved as a StringTag in older versions of PM)
$skinTag->getByteArray("CapeData", ""),
$skinTag->getString("GeometryName", ""),
$skinTag->getByteArray("GeometryData", "")
);
$skin->validate();
return $skin;
}
/**
* @deprecated
*
* Checks the length of a supplied skin bitmap and returns whether the length is valid.
*
* @param string $skin
@ -124,7 +136,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
* @return bool
*/
public static function isValidSkin(string $skin) : bool{
return strlen($skin) === 64 * 64 * 4 or strlen($skin) === 64 * 32 * 4 or strlen($skin) === 128 * 128 * 4;
return in_array(strlen($skin), Skin::ACCEPTED_SKIN_SIZES, true);
}
/**
@ -156,10 +168,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
* @param Skin $skin
*/
public function setSkin(Skin $skin) : void{
if(!$skin->isValid()){
throw new \InvalidStateException("Specified skin is not valid, must be 8KiB or 16KiB");
}
$skin->validate();
$this->skin = $skin;
$this->skin->debloatGeometryData();
}
@ -203,18 +212,13 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$old = $attr->getValue();
$attr->setValue($new);
$reset = false;
// ranges: 18-20 (regen), 7-17 (none), 1-6 (no sprint), 0 (health depletion)
foreach([17, 6, 0] as $bound){
if(($old > $bound) !== ($new > $bound)){
$reset = true;
$this->foodTickTimer = 0;
break;
}
}
if($reset){
$this->foodTickTimer = 0;
}
}
public function getMaxFood() : float{
@ -301,7 +305,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$food = $this->getFood();
if($food > 0){
$food--;
$this->setFood($food);
$this->setFood(max($food, 0));
}
}
}
@ -599,17 +603,6 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$this->setNameTag($this->namedtag->getString("NameTag"));
}
$skin = $this->namedtag->getCompoundTag("Skin");
if($skin !== null){
$this->setSkin(new Skin(
$skin->getString("Name"),
$skin->hasTag("Data", StringTag::class) ? $skin->getString("Data") : $skin->getByteArray("Data"), //old data (this used to be saved as a StringTag in older versions of PM)
$skin->getByteArray("CapeData", ""),
$skin->getString("GeometryName", ""),
$skin->getByteArray("GeometryData", "")
));
}
$this->uuid = UUID::fromData((string) $this->getId(), $this->skin->getSkinData(), $this->getNameTag());
}
@ -635,7 +628,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
//Old hotbar saving stuff, ignore it
}elseif($slot >= 100 and $slot < 104){ //Armor
$this->armorInventory->setItem($slot - 100, Item::nbtDeserialize($item));
}else{
}elseif($slot >= 9 and $slot < $this->inventory->getSize() + 9){
$this->inventory->setItem($slot - 9, Item::nbtDeserialize($item));
}
}
@ -761,7 +754,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
$this->addEffect(new EffectInstance(Effect::getEffect(Effect::FIRE_RESISTANCE), 40 * 20, 1));
$this->addEffect(new EffectInstance(Effect::getEffect(Effect::ABSORPTION), 5 * 20, 1));
$this->broadcastEntityEvent(EntityEventPacket::CONSUME_TOTEM);
$this->broadcastEntityEvent(ActorEventPacket::CONSUME_TOTEM);
$this->level->broadcastLevelEvent($this->add(0, $this->eyeHeight, 0), LevelEventPacket::EVENT_SOUND_TOTEM);
$hand = $this->inventory->getItemInHand();
@ -848,9 +841,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{
}
protected function sendSpawnPacket(Player $player) : void{
if(!$this->skin->isValid()){
throw new \InvalidStateException((new \ReflectionClass($this))->getShortName() . " must have a valid skin set");
}
$this->skin->validate();
if(!($this instanceof Player)){
/* we don't use Server->updatePlayerListData() because that uses batches, which could cause race conditions in async compression mode */

View File

@ -44,7 +44,7 @@ use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\FloatTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\nbt\tag\ListTag;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\MobEffectPacket;
use pocketmine\Player;
@ -143,7 +143,7 @@ abstract class Living extends Entity implements Damageable{
parent::setHealth($amount);
$this->attributeMap->getAttribute(Attribute::HEALTH)->setValue(ceil($this->getHealth()), true);
if($this->isAlive() and !$wasAlive){
$this->broadcastEntityEvent(EntityEventPacket::RESPAWN);
$this->broadcastEntityEvent(ActorEventPacket::RESPAWN);
}
}
@ -152,7 +152,7 @@ abstract class Living extends Entity implements Damageable{
}
public function setMaxHealth(int $amount) : void{
$this->attributeMap->getAttribute(Attribute::HEALTH)->setMaxValue($amount);
$this->attributeMap->getAttribute(Attribute::HEALTH)->setMaxValue($amount)->setDefaultValue($amount);
}
public function getAbsorption() : float{
@ -541,7 +541,9 @@ abstract class Living extends Entity implements Damageable{
}
public function attack(EntityDamageEvent $source) : void{
if($this->attackTime > 0 or $this->noDamageTicks > 0){
if($this->noDamageTicks > 0){
$source->setCancelled();
}elseif($this->attackTime > 0){
$lastCause = $this->getLastDamageCause();
if($lastCause !== null and $lastCause->getBaseDamage() >= $source->getBaseDamage()){
$source->setCancelled();
@ -604,7 +606,7 @@ abstract class Living extends Entity implements Damageable{
}
protected function doHitAnimation() : void{
$this->broadcastEntityEvent(EntityEventPacket::HURT_ANIMATION);
$this->broadcastEntityEvent(ActorEventPacket::HURT_ANIMATION);
}
public function knockBack(Entity $attacker, float $damage, float $x, float $z, float $base = 0.4) : void{
@ -662,7 +664,7 @@ abstract class Living extends Entity implements Damageable{
}
protected function startDeathAnimation() : void{
$this->broadcastEntityEvent(EntityEventPacket::DEATH_ANIMATION);
$this->broadcastEntityEvent(ActorEventPacket::DEATH_ANIMATION);
}
protected function endDeathAnimation() : void{

View File

@ -23,11 +23,18 @@ declare(strict_types=1);
namespace pocketmine\entity;
use function implode;
use function in_array;
use function json_decode;
use function json_encode;
use function strlen;
class Skin{
public const ACCEPTED_SKIN_SIZES = [
64 * 32 * 4,
64 * 64 * 4,
128 * 128 * 4
];
/** @var string */
private $skinId;
@ -48,12 +55,34 @@ class Skin{
$this->geometryData = $geometryData;
}
/**
* @deprecated
* @return bool
*/
public function isValid() : bool{
return (
$this->skinId !== "" and
(($s = strlen($this->skinData)) === 16384 or $s === 8192 or $s === 65536) and
($this->capeData === "" or strlen($this->capeData) === 8192)
);
try{
$this->validate();
return true;
}catch(\InvalidArgumentException $e){
return false;
}
}
/**
* @throws \InvalidArgumentException
*/
public function validate() : void{
if($this->skinId === ""){
throw new \InvalidArgumentException("Skin ID must not be empty");
}
$len = strlen($this->skinData);
if(!in_array($len, self::ACCEPTED_SKIN_SIZES, true)){
throw new \InvalidArgumentException("Invalid skin data size $len bytes (allowed sizes: " . implode(", ", self::ACCEPTED_SKIN_SIZES) . ")");
}
if($this->capeData !== "" and strlen($this->capeData) !== 8192){
throw new \InvalidArgumentException("Invalid cape data size " . strlen($this->capeData) . " bytes (must be exactly 8192 bytes)");
}
//TODO: validate geometry
}
/**

View File

@ -28,7 +28,7 @@ use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use function atan2;
use function mt_rand;
use function sqrt;
@ -68,7 +68,7 @@ class Squid extends WaterAnimal{
$this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize();
}
$this->broadcastEntityEvent(EntityEventPacket::SQUID_INK_CLOUD);
$this->broadcastEntityEvent(ActorEventPacket::SQUID_INK_CLOUD);
}
}

View File

@ -28,8 +28,8 @@ use pocketmine\event\entity\ItemDespawnEvent;
use pocketmine\event\entity\ItemSpawnEvent;
use pocketmine\event\inventory\InventoryPickupItemEvent;
use pocketmine\item\Item;
use pocketmine\network\mcpe\protocol\AddItemEntityPacket;
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
use pocketmine\network\mcpe\protocol\AddItemActorPacket;
use pocketmine\network\mcpe\protocol\TakeItemActorPacket;
use pocketmine\Player;
use function get_class;
@ -192,7 +192,7 @@ class ItemEntity extends Entity{
}
protected function sendSpawnPacket(Player $player) : void{
$pk = new AddItemEntityPacket();
$pk = new AddItemActorPacket();
$pk->entityRuntimeId = $this->getId();
$pk->position = $this->asVector3();
$pk->motion = $this->getMotion();
@ -229,7 +229,7 @@ class ItemEntity extends Entity{
break;
}
$pk = new TakeItemEntityPacket();
$pk = new TakeItemActorPacket();
$pk->eid = $player->getId();
$pk->target = $this->getId();
$this->server->broadcastPacket($this->getViewers(), $pk);

View File

@ -152,9 +152,11 @@ class Painting extends Entity{
protected function sendSpawnPacket(Player $player) : void{
$pk = new AddPaintingPacket();
$pk->entityRuntimeId = $this->getId();
$pk->x = $this->blockIn->x;
$pk->y = $this->blockIn->y;
$pk->z = $this->blockIn->z;
$pk->position = new Vector3(
($this->boundingBox->minX + $this->boundingBox->maxX) / 2,
($this->boundingBox->minY + $this->boundingBox->maxY) / 2,
($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2
);
$pk->direction = $this->direction;
$pk->title = $this->motive;

View File

@ -32,9 +32,9 @@ use pocketmine\item\ItemFactory;
use pocketmine\level\Level;
use pocketmine\math\RayTraceResult;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\network\mcpe\protocol\EntityEventPacket;
use pocketmine\network\mcpe\protocol\ActorEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\TakeItemEntityPacket;
use pocketmine\network\mcpe\protocol\TakeItemActorPacket;
use pocketmine\Player;
use function mt_rand;
use function sqrt;
@ -123,7 +123,7 @@ class Arrow extends Projectile{
$hasUpdate = parent::entityBaseTick($tickDiff);
if($this->isCollided){
if($this->blockHit !== null){
$this->collideTicks += $tickDiff;
if($this->collideTicks > 1200){
$this->flagForDespawn();
@ -143,7 +143,7 @@ class Arrow extends Projectile{
protected function onHitBlock(Block $blockHit, RayTraceResult $hitResult) : void{
parent::onHitBlock($blockHit, $hitResult);
$this->broadcastEntityEvent(EntityEventPacket::ARROW_SHAKE, 7); //7 ticks
$this->broadcastEntityEvent(ActorEventPacket::ARROW_SHAKE, 7); //7 ticks
}
protected function onHitEntity(Entity $entityHit, RayTraceResult $hitResult) : void{
@ -193,7 +193,7 @@ class Arrow extends Projectile{
return;
}
$pk = new TakeItemEntityPacket();
$pk = new TakeItemActorPacket();
$pk->eid = $player->getId();
$pk->target = $this->getId();
$this->server->broadcastPacket($this->getViewers(), $pk);

View File

@ -50,8 +50,6 @@ use const PHP_INT_MAX;
abstract class Projectile extends Entity{
public const DATA_SHOOTER_ID = 17;
/** @var float */
protected $damage = 0.0;

View File

@ -67,10 +67,7 @@ class PlayerChangeSkinEvent extends PlayerEvent implements Cancellable{
* @throws \InvalidArgumentException if the specified skin is not valid
*/
public function setNewSkin(Skin $skin) : void{
if(!$skin->isValid()){
throw new \InvalidArgumentException("Skin format is invalid");
}
$skin->validate();
$this->newSkin = $skin;
}
}

View File

@ -27,7 +27,7 @@ use pocketmine\level\Position;
use pocketmine\Player;
/**
* Called when a player is respawned (or first time spawned)
* Called when a player is respawned
*/
class PlayerRespawnEvent extends PlayerEvent{
/** @var Position */

View File

@ -35,8 +35,6 @@ use function substr;
class QueryRegenerateEvent extends ServerEvent{
public const GAME_ID = "MINECRAFTPE";
/** @var int */
private $timeout;
/** @var string */
private $serverName;
/** @var bool */
@ -68,13 +66,16 @@ class QueryRegenerateEvent extends ServerEvent{
/** @var array */
private $extraData = [];
/** @var string|null */
private $longQueryCache = null;
/** @var string|null */
private $shortQueryCache = null;
/**
* @param Server $server
* @param int $timeout
*/
public function __construct(Server $server, int $timeout = 5){
$this->timeout = $timeout;
public function __construct(Server $server){
$this->serverName = $server->getMotd();
$this->listPlugins = $server->getProperty("settings.query-plugins", true);
$this->plugins = $server->getPluginManager()->getPlugins();
@ -98,19 +99,25 @@ class QueryRegenerateEvent extends ServerEvent{
}
/**
* Gets the min. timeout for Query Regeneration
* @deprecated
*
* @return int
*/
public function getTimeout() : int{
return $this->timeout;
return 0;
}
/**
* @deprecated
* @param int $timeout
*/
public function setTimeout(int $timeout) : void{
$this->timeout = $timeout;
}
private function destroyCache() : void{
$this->longQueryCache = null;
$this->shortQueryCache = null;
}
/**
@ -125,6 +132,7 @@ class QueryRegenerateEvent extends ServerEvent{
*/
public function setServerName(string $serverName) : void{
$this->serverName = $serverName;
$this->destroyCache();
}
/**
@ -139,6 +147,7 @@ class QueryRegenerateEvent extends ServerEvent{
*/
public function setListPlugins(bool $value) : void{
$this->listPlugins = $value;
$this->destroyCache();
}
/**
@ -153,6 +162,7 @@ class QueryRegenerateEvent extends ServerEvent{
*/
public function setPlugins(array $plugins) : void{
$this->plugins = $plugins;
$this->destroyCache();
}
/**
@ -167,6 +177,7 @@ class QueryRegenerateEvent extends ServerEvent{
*/
public function setPlayerList(array $players) : void{
$this->players = $players;
$this->destroyCache();
}
/**
@ -181,6 +192,7 @@ class QueryRegenerateEvent extends ServerEvent{
*/
public function setPlayerCount(int $count) : void{
$this->numPlayers = $count;
$this->destroyCache();
}
/**
@ -195,6 +207,7 @@ class QueryRegenerateEvent extends ServerEvent{
*/
public function setMaxPlayerCount(int $count) : void{
$this->maxPlayers = $count;
$this->destroyCache();
}
/**
@ -209,6 +222,7 @@ class QueryRegenerateEvent extends ServerEvent{
*/
public function setWorld(string $world) : void{
$this->map = $world;
$this->destroyCache();
}
/**
@ -225,12 +239,16 @@ class QueryRegenerateEvent extends ServerEvent{
*/
public function setExtraData(array $extraData) : void{
$this->extraData = $extraData;
$this->destroyCache();
}
/**
* @return string
*/
public function getLongQuery() : string{
if($this->longQueryCache !== null){
return $this->longQueryCache;
}
$query = "";
$plist = $this->server_engine;
@ -273,13 +291,13 @@ class QueryRegenerateEvent extends ServerEvent{
}
$query .= "\x00";
return $query;
return $this->longQueryCache = $query;
}
/**
* @return string
*/
public function getShortQuery() : string{
return $this->serverName . "\x00" . $this->gametype . "\x00" . $this->map . "\x00" . $this->numPlayers . "\x00" . $this->maxPlayers . "\x00" . Binary::writeLShort($this->port) . $this->ip . "\x00";
return $this->shortQueryCache ?? ($this->shortQueryCache = $this->serverName . "\x00" . $this->gametype . "\x00" . $this->map . "\x00" . $this->numPlayers . "\x00" . $this->maxPlayers . "\x00" . Binary::writeLShort($this->port) . $this->ip . "\x00");
}
}

View File

@ -59,6 +59,9 @@ class AnvilInventory extends ContainerInventory{
public function onClose(Player $who) : void{
parent::onClose($who);
$this->dropContents($this->holder->getLevel(), $this->holder->add(0.5, 0.5, 0.5));
foreach($this->getContents() as $item){
$who->dropItem($item);
}
$this->clearAll();
}
}

View File

@ -94,11 +94,12 @@ class ArmorInventory extends BaseInventory{
$target = [$target];
}
$armor = $this->getContents(true);
$pk = new MobArmorEquipmentPacket();
$pk->entityRuntimeId = $this->getHolder()->getId();
$pk->slots = $armor;
$pk->head = $this->getHelmet();
$pk->chest = $this->getChestplate();
$pk->legs = $this->getLeggings();
$pk->feet = $this->getBoots();
$pk->encode();
foreach($target as $player){
@ -121,18 +122,19 @@ class ArmorInventory extends BaseInventory{
$target = [$target];
}
$armor = $this->getContents(true);
$pk = new MobArmorEquipmentPacket();
$pk->entityRuntimeId = $this->getHolder()->getId();
$pk->slots = $armor;
$pk->head = $this->getHelmet();
$pk->chest = $this->getChestplate();
$pk->legs = $this->getLeggings();
$pk->feet = $this->getBoots();
$pk->encode();
foreach($target as $player){
if($player === $this->getHolder()){
$pk2 = new InventoryContentPacket();
$pk2->windowId = $player->getWindowId($this);
$pk2->items = $armor;
$pk2->items = $this->getContents(true);
$player->dataPacket($pk2);
}else{
$player->dataPacket($pk);

View File

@ -253,11 +253,9 @@ abstract class BaseInventory implements Inventory{
public function canAddItem(Item $item) : bool{
$item = clone $item;
$checkDamage = !$item->hasAnyDamageValue();
$checkTags = $item->hasCompoundTag();
for($i = 0, $size = $this->getSize(); $i < $size; ++$i){
$slot = $this->getItem($i);
if($item->equals($slot, $checkDamage, $checkTags)){
if($item->equals($slot)){
if(($diff = $slot->getMaxStackSize() - $slot->getCount()) > 0){
$item->setCount($item->getCount() - $diff);
}

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\inventory;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\CraftingDataPacket;
use pocketmine\Server;
@ -54,26 +53,36 @@ class CraftingManager{
public function init() : void{
$recipes = json_decode(file_get_contents(\pocketmine\RESOURCE_PATH . "vanilla" . DIRECTORY_SEPARATOR . "recipes.json"), true);
$itemDeserializerFunc = \Closure::fromCallable([Item::class, 'jsonDeserialize']);
foreach($recipes as $recipe){
switch($recipe["type"]){
case 0:
case "shapeless":
if($recipe["block"] !== "crafting_table"){ //TODO: filter others out for now to avoid breaking economics
break;
}
$this->registerRecipe(new ShapelessRecipe(
array_map(function(array $data) : Item{ return Item::jsonDeserialize($data); }, $recipe["input"]),
array_map(function(array $data) : Item{ return Item::jsonDeserialize($data); }, $recipe["output"])
array_map($itemDeserializerFunc, $recipe["input"]),
array_map($itemDeserializerFunc, $recipe["output"])
));
break;
case 1:
case "shaped":
if($recipe["block"] !== "crafting_table"){ //TODO: filter others out for now to avoid breaking economics
break;
}
$this->registerRecipe(new ShapedRecipe(
$recipe["shape"],
array_map(function(array $data) : Item{ return Item::jsonDeserialize($data); }, $recipe["input"]),
array_map(function(array $data) : Item{ return Item::jsonDeserialize($data); }, $recipe["output"])
array_map($itemDeserializerFunc, $recipe["input"]),
array_map($itemDeserializerFunc, $recipe["output"])
));
break;
case 2:
case 3:
$result = $recipe["output"];
$resultItem = Item::jsonDeserialize($result);
$this->registerRecipe(new FurnaceRecipe($resultItem, ItemFactory::get($recipe["inputId"], $recipe["inputDamage"] ?? -1, 1)));
case "smelting":
if($recipe["block"] !== "furnace"){ //TODO: filter others out for now to avoid breaking economics
break;
}
$this->registerRecipe(new FurnaceRecipe(
Item::jsonDeserialize($recipe["output"]),
Item::jsonDeserialize($recipe["input"]))
);
break;
default:
break;

View File

@ -59,6 +59,9 @@ class EnchantInventory extends ContainerInventory{
public function onClose(Player $who) : void{
parent::onClose($who);
$this->dropContents($this->holder->getLevel(), $this->holder->add(0.5, 0.5, 0.5));
foreach($this->getContents() as $item){
$who->dropItem($item);
}
$this->clearAll();
}
}

View File

@ -28,12 +28,16 @@ use pocketmine\utils\UUID;
class MultiRecipe{
public const TYPE_REPAIR_ITEM = "00000000-0000-0000-0000-000000000001";
public const TYPE_MAP_EXTENDING = "D392B075-4BA1-40AE-8789-AF868D56F6CE";
public const TYPE_MAP_EXTENDING_CARTOGRAPHY = "8B36268C-1829-483C-A0F1-993B7156A8F2";
public const TYPE_MAP_CLONING = "85939755-BA10-4D9D-A4CC-EFB7A8E943C4";
public const TYPE_MAP_CLONING_CARTOGRAPHY = "442D85ED-8272-4543-A6F1-418F90DED05D";
public const TYPE_MAP_UPGRADING = "AECD2294-4B94-434B-8667-4499BB2C9327";
public const TYPE_MAP_UPGRADING_CARTOGRAPHY = "98C84B38-1085-46BD-B1CE-DD38C159E6CC";
public const TYPE_BOOK_CLONING = "D1CA6B84-338E-4F2F-9C6B-76CC8B4BD98D";
public const TYPE_BANNER_DUPLICATE = "B5C5D105-75A2-4076-AF2B-923EA2BF4BF0";
public const TYPE_BANNER_ADD_PATTERN = "D81AAEAF-E172-4440-9225-868DF030D27B";
public const TYPE_FIREWORKS = "00000000-0000-0000-0000-000000000002";
public const TYPE_MAP_LOCKING_CARTOGRAPHY = "602234E4-CAC1-4353-8BB7-B1EBFF70024B";
private $uuid;

View File

@ -32,6 +32,21 @@ use function array_pop;
use function count;
use function intdiv;
/**
* This transaction type is specialized for crafting validation. It shares most of the same semantics of the base
* inventory transaction type, but the requirement for validity is slightly different.
*
* It is expected that the actions in this transaction type will produce an **unbalanced result**, i.e. some inputs won't
* have corresponding outputs, and vice versa. The reason why is because the unmatched inputs are recipe inputs, and
* the unmatched outputs are recipe results.
*
* Therefore, the validity requirement is that the imbalance of the transaction should match the expected inputs and
* outputs of a registered crafting recipe.
*
* This transaction allows multiple repetitions of the same recipe to be crafted in a single batch. In the case of batch
* crafting, the number of unmatched inputs and outputs must be exactly divisible by the expected recipe ingredients and
* results, with no remainder. Any leftovers are expected to be emitted back to the crafting grid.
*/
class CraftingTransaction extends InventoryTransaction{
/** @var CraftingRecipe|null */
protected $recipe;

View File

@ -29,14 +29,28 @@ use pocketmine\inventory\transaction\action\InventoryAction;
use pocketmine\inventory\transaction\action\SlotChangeAction;
use pocketmine\item\Item;
use pocketmine\Player;
use function array_keys;
use function assert;
use function count;
use function get_class;
use function min;
use function shuffle;
use function spl_object_hash;
/**
* This InventoryTransaction only allows doing Transaction between one / two inventories
* This is the basic type for an inventory transaction. This is used for moving items between inventories, dropping
* items and more. It allows transactions with multiple inputs and outputs.
*
* Validation **does not** depend on ordering. This means that the actions can appear in any order and still be valid.
* The only validity requirement for this transaction type is that the balance of items must add up to zero. This means:
* - No new outputs without matching input amounts
* - No inputs without matching output amounts
* - No userdata changes (item state, NBT, etc)
*
* A transaction is composed of "actions", which are pairs of inputs and outputs which target a specific itemstack in
* a specific location. There are multiple types of inventory actions which might be involved in a transaction.
*
* @see InventoryAction
*/
class InventoryTransaction{
protected $hasExecuted = false;
@ -75,6 +89,11 @@ class InventoryTransaction{
}
/**
* Returns an **unordered** set of actions involved in this transaction.
*
* WARNING: This system is **explicitly designed NOT to care about ordering**. Any order seen in this set has NO
* significance and should not be relied on.
*
* @return InventoryAction[]
*/
public function getActions() : array{
@ -93,6 +112,19 @@ class InventoryTransaction{
}
}
/**
* Shuffles actions in the transaction to prevent external things relying on any implicit ordering.
*/
private function shuffleActions() : void{
$keys = array_keys($this->actions);
shuffle($keys);
$actions = [];
foreach($keys as $key){
$actions[$key] = $this->actions[$key];
}
$this->actions = $actions;
}
/**
* @internal This method should not be used by plugins, it's used to add tracked inventories for InventoryActions
* involving inventories.
@ -271,6 +303,8 @@ class InventoryTransaction{
return false;
}
$this->shuffleActions();
$this->validate();
if(!$this->callExecuteEvent()){

View File

@ -46,7 +46,6 @@ use pocketmine\utils\Binary;
use function array_map;
use function base64_decode;
use function base64_encode;
use function bin2hex;
use function file_get_contents;
use function get_class;
use function hex2bin;
@ -216,7 +215,7 @@ class Item implements ItemIds, \JsonSerializable{
/**
* Sets the Item's NBT
*
* @param CompoundTag|string $tags
* @param CompoundTag|string|null $tags
*
* @return Item
*/
@ -224,7 +223,7 @@ class Item implements ItemIds, \JsonSerializable{
if($tags instanceof CompoundTag){
$this->setNamedTag($tags);
}else{
$this->tags = (string) $tags;
$this->tags = $tags === null ? "" : (string) $tags;
$this->cachedNBT = null;
}
@ -232,6 +231,9 @@ class Item implements ItemIds, \JsonSerializable{
}
/**
* @deprecated This method returns NBT serialized in a network-dependent format. Prefer use of getNamedTag() instead.
* @see Item::getNamedTag()
*
* Returns the serialized NBT of the Item
* @return string
*/
@ -871,7 +873,7 @@ class Item implements ItemIds, \JsonSerializable{
* @return string
*/
final public function __toString() : string{
return "Item " . $this->name . " (" . $this->id . ":" . ($this->hasAnyDamageValue() ? "?" : $this->meta) . ")x" . $this->count . ($this->hasCompoundTag() ? " tags:0x" . bin2hex($this->getCompoundTag()) : "");
return "Item " . $this->name . " (" . $this->id . ":" . ($this->hasAnyDamageValue() ? "?" : $this->meta) . ")x" . $this->count . ($this->hasCompoundTag() ? " tags:" . base64_encode($this->getCompoundTag()) : "");
}
/**

View File

@ -300,16 +300,16 @@ class ItemFactory{
/**
* Returns an instance of the Item with the specified id, meta, count and NBT.
*
* @param int $id
* @param int $meta
* @param int $count
* @param CompoundTag|string $tags
* @param int $id
* @param int $meta
* @param int $count
* @param CompoundTag|string|null $tags
*
* @return Item
* @throws \TypeError
*/
public static function get(int $id, int $meta = 0, int $count = 1, $tags = "") : Item{
if(!is_string($tags) and !($tags instanceof CompoundTag)){
public static function get(int $id, int $meta = 0, int $count = 1, $tags = null) : Item{
if(!is_string($tags) and !($tags instanceof CompoundTag) and $tags !== null){
throw new \TypeError("`tags` argument must be a string or CompoundTag instance, " . (is_object($tags) ? "instance of " . get_class($tags) : gettype($tags)) . " given");
}
@ -318,7 +318,7 @@ class ItemFactory{
$listed = self::$list[self::getListOffset($id)];
if($listed !== null){
$item = clone $listed;
}elseif($id < 256){ //intentionally includes negatives, for extended block IDs
}elseif($id >= 0 and $id < 256){ //intentionally excludes negatives because extended blocks aren't supported yet
/* Blocks must have a damage value 0-15, but items can have damage value -1 to indicate that they are
* crafting ingredients with any-damage. */
$item = new ItemBlock($id, $meta);

View File

@ -204,6 +204,7 @@ interface ItemIds extends BlockIds{
public const DARK_OAK_DOOR = 431;
public const CHORUS_FRUIT = 432;
public const CHORUS_FRUIT_POPPED = 433;
public const BANNER_PATTERN = 434;
public const DRAGON_BREATH = 437;
public const SPLASH_POTION = 438;
@ -237,6 +238,14 @@ interface ItemIds extends BlockIds{
public const HEART_OF_THE_SEA = 467;
public const TURTLE_SHELL_PIECE = 468;
public const TURTLE_HELMET = 469;
public const PHANTOM_MEMBRANE = 470;
public const CROSSBOW = 471;
public const SPRUCE_SIGN = 472;
public const BIRCH_SIGN = 473;
public const JUNGLE_SIGN = 474;
public const ACACIA_SIGN = 475;
public const DARKOAK_SIGN = 476;
public const SWEET_BERRIES = 477;
public const COMPOUND = 499;
public const RECORD_13 = 500;
@ -252,4 +261,6 @@ interface ItemIds extends BlockIds{
public const RECORD_11 = 510;
public const RECORD_WAIT = 511;
public const SHIELD = 513;
}

View File

@ -74,7 +74,7 @@ class Explosion{
*/
public function __construct(Position $center, float $size, $what = null){
if(!$center->isValid()){
throw new \InvalidArgumentException("Position does not have a valid level");
throw new \InvalidArgumentException("Position does not have a valid world");
}
$this->source = $center;
$this->level = $center->getLevel();

View File

@ -26,6 +26,7 @@ declare(strict_types=1);
*/
namespace pocketmine\level;
use pocketmine\block\Air;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\entity\Entity;
@ -71,13 +72,14 @@ use pocketmine\metadata\Metadatable;
use pocketmine\metadata\MetadataValue;
use pocketmine\nbt\tag\ListTag;
use pocketmine\nbt\tag\StringTag;
use pocketmine\network\mcpe\protocol\AddEntityPacket;
use pocketmine\network\mcpe\protocol\AddActorPacket;
use pocketmine\network\mcpe\protocol\BatchPacket;
use pocketmine\network\mcpe\protocol\DataPacket;
use pocketmine\network\mcpe\protocol\LevelEventPacket;
use pocketmine\network\mcpe\protocol\LevelSoundEventPacket;
use pocketmine\network\mcpe\protocol\SetDifficultyPacket;
use pocketmine\network\mcpe\protocol\SetTimePacket;
use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping;
use pocketmine\network\mcpe\protocol\UpdateBlockPacket;
use pocketmine\Player;
use pocketmine\plugin\Plugin;
@ -111,6 +113,8 @@ use function trim;
use const INT32_MAX;
use const INT32_MIN;
use const M_PI;
use const PHP_INT_MAX;
use const PHP_INT_MIN;
#include <rules/Level.h>
@ -261,11 +265,12 @@ class Level implements ChunkManager, Metadatable{
/** @var LevelTimings */
public $timings;
/** @var int */
private $tickRate;
/** @var int */
public $tickRateTime = 0;
/** @var int */
/**
* @deprecated
* @var int
*/
public $tickRateCounter = 0;
/** @var bool */
@ -381,7 +386,7 @@ class Level implements ChunkManager, Metadatable{
$this->worldHeight = $this->provider->getWorldHeight();
$this->server->getLogger()->info($this->server->getLanguage()->translateString("pocketmine.level.preparing", [$this->displayName]));
$this->generator = GeneratorManager::getGenerator($this->provider->getGenerator());
$this->generator = GeneratorManager::getGenerator($this->provider->getGenerator(), true);
//TODO: validate generator options
$this->folderName = $name;
@ -411,19 +416,26 @@ class Level implements ChunkManager, Metadatable{
$this->timings = new LevelTimings($this);
$this->temporalPosition = new Position(0, 0, 0, $this);
$this->temporalVector = new Vector3(0, 0, 0);
$this->tickRate = 1;
}
/**
* @deprecated
* @return int
*/
public function getTickRate() : int{
return $this->tickRate;
return 1;
}
public function getTickRateTime() : float{
return $this->tickRateTime;
}
/**
* @deprecated does nothing
* @param int $tickRate
*/
public function setTickRate(int $tickRate){
$this->tickRate = $tickRate;
}
public function registerGeneratorToWorker(int $worker) : void{
@ -466,7 +478,7 @@ class Level implements ChunkManager, Metadatable{
public function close(){
if($this->closed){
throw new \InvalidStateException("Tried to close a level which is already closed");
throw new \InvalidStateException("Tried to close a world which is already closed");
}
foreach($this->chunks as $chunk){
@ -552,7 +564,7 @@ class Level implements ChunkManager, Metadatable{
$pk = new LevelSoundEventPacket();
$pk->sound = $soundId;
$pk->extraData = $extraData;
$pk->entityType = AddEntityPacket::LEGACY_ID_MAP_BC[$entityTypeId] ?? ":";
$pk->entityType = AddActorPacket::LEGACY_ID_MAP_BC[$entityTypeId] ?? ":";
$pk->isBabyMob = $isBabyMob;
$pk->disableRelativeVolume = $disableRelativeVolume;
$pk->position = $pos->asVector3();
@ -580,7 +592,7 @@ class Level implements ChunkManager, Metadatable{
*/
public function unload(bool $force = false) : bool{
if($this->doingTick and !$force){
throw new \InvalidStateException("Cannot unload a level during level tick");
throw new \InvalidStateException("Cannot unload a world during world tick");
}
$ev = new LevelUnloadEvent($this);
@ -599,7 +611,7 @@ class Level implements ChunkManager, Metadatable{
$defaultLevel = $this->server->getDefaultLevel();
foreach($this->getPlayers() as $player){
if($this === $defaultLevel or $defaultLevel === null){
$player->close($player->getLeaveMessage(), "Forced default level unload");
$player->close($player->getLeaveMessage(), "Forced default world unload");
}elseif($defaultLevel instanceof Level){
$player->teleport($this->server->getDefaultLevel()->getSafeSpawn());
}
@ -746,17 +758,6 @@ class Level implements ChunkManager, Metadatable{
}
}
/**
* @internal
*/
public function checkTime(){
if($this->stopTime){
return;
}else{
++$this->time;
}
}
/**
* @internal
*
@ -764,7 +765,7 @@ class Level implements ChunkManager, Metadatable{
*/
public function sendTime(Player ...$targets){
$pk = new SetTimePacket();
$pk->time = $this->time;
$pk->time = $this->time & 0xffffffff; //avoid overflowing the field, since the packet uses an int32
$this->server->broadcastPacket(count($targets) > 0 ? $targets : $this->players, $pk);
}
@ -777,7 +778,7 @@ class Level implements ChunkManager, Metadatable{
*/
public function doTick(int $currentTick){
if($this->closed){
throw new \InvalidStateException("Attempted to tick a Level which has been closed");
throw new \InvalidStateException("Attempted to tick a world which has been closed");
}
$this->timings->doTick->startTiming();
@ -791,7 +792,14 @@ class Level implements ChunkManager, Metadatable{
}
protected function actuallyDoTick(int $currentTick) : void{
$this->checkTime();
if(!$this->stopTime){
//this simulates an overflow, as would happen in any language which doesn't do stupid things to var types
if($this->time === PHP_INT_MAX){
$this->time = PHP_INT_MIN;
}else{
$this->time++;
}
}
$this->sunAnglePercentage = $this->computeSunAnglePercentage(); //Sun angle depends on the current time
$this->skyLightReduction = $this->computeSkyLightReduction(); //Sky light reduction depends on the sun angle
@ -974,7 +982,7 @@ class Level implements ChunkManager, Metadatable{
$pk->blockRuntimeId = $b->getRuntimeId();
}else{
$fullBlock = $this->getFullBlock($b->x, $b->y, $b->z);
$pk->blockRuntimeId = BlockFactory::toStaticRuntimeId($fullBlock >> 4, $fullBlock & 0xf);
$pk->blockRuntimeId = RuntimeBlockMapping::toStaticRuntimeId($fullBlock >> 4, $fullBlock & 0xf);
}
$pk->flags = $first ? $flags : UpdateBlockPacket::FLAG_NONE;
@ -996,7 +1004,7 @@ class Level implements ChunkManager, Metadatable{
$pk->blockRuntimeId = $b->getRuntimeId();
}else{
$fullBlock = $this->getFullBlock($b->x, $b->y, $b->z);
$pk->blockRuntimeId = BlockFactory::toStaticRuntimeId($fullBlock >> 4, $fullBlock & 0xf);
$pk->blockRuntimeId = RuntimeBlockMapping::toStaticRuntimeId($fullBlock >> 4, $fullBlock & 0xf);
}
$pk->flags = $flags;
@ -1149,11 +1157,16 @@ class Level implements ChunkManager, Metadatable{
}
public function saveChunks(){
foreach($this->chunks as $chunk){
if(($chunk->hasChanged() or count($chunk->getTiles()) > 0 or count($chunk->getSavableEntities()) > 0) and $chunk->isGenerated()){
$this->provider->saveChunk($chunk);
$chunk->setChanged(false);
$this->timings->syncChunkSaveTimer->startTiming();
try{
foreach($this->chunks as $chunk){
if(($chunk->hasChanged() or count($chunk->getTiles()) > 0 or count($chunk->getSavableEntities()) > 0) and $chunk->isGenerated()){
$this->provider->saveChunk($chunk);
$chunk->setChanged(false);
}
}
}finally{
$this->timings->syncChunkSaveTimer->stopTiming();
}
}
@ -1785,7 +1798,7 @@ class Level implements ChunkManager, Metadatable{
if($player !== null){
$ev = new BlockBreakEvent($player, $target, $item, $player->isCreative(), $drops, $xpDrop);
if(($player->isSurvival() and !$target->isBreakable($item)) or $player->isSpectator()){
if($target instanceof Air or ($player->isSurvival() and !$target->isBreakable($item)) or $player->isSpectator()){
$ev->setCancelled();
}elseif($this->checkSpawnProtection($player, $target)){
$ev->setCancelled(); //set it to cancelled so plugins can bypass this
@ -1884,7 +1897,7 @@ class Level implements ChunkManager, Metadatable{
$clickVector = new Vector3(0.0, 0.0, 0.0);
}
if($blockReplace->y >= $this->worldHeight or $blockReplace->y < 0){
if(!$this->isInWorld($blockReplace->x, $blockReplace->y, $blockReplace->z)){
//TODO: build height limit messages for custom world heights and mcregion cap
return false;
}
@ -2691,10 +2704,10 @@ class Level implements ChunkManager, Metadatable{
*/
public function addEntity(Entity $entity){
if($entity->isClosed()){
throw new \InvalidArgumentException("Attempted to add a garbage closed Entity to Level");
throw new \InvalidArgumentException("Attempted to add a garbage closed Entity to world");
}
if($entity->getLevel() !== $this){
throw new LevelException("Invalid Entity level");
throw new LevelException("Invalid Entity world");
}
if($entity instanceof Player){
@ -2712,7 +2725,7 @@ class Level implements ChunkManager, Metadatable{
*/
public function removeEntity(Entity $entity){
if($entity->getLevel() !== $this){
throw new LevelException("Invalid Entity level");
throw new LevelException("Invalid Entity world");
}
if($entity instanceof Player){
@ -2731,10 +2744,10 @@ class Level implements ChunkManager, Metadatable{
*/
public function addTile(Tile $tile){
if($tile->isClosed()){
throw new \InvalidArgumentException("Attempted to add a garbage closed Tile to Level");
throw new \InvalidArgumentException("Attempted to add a garbage closed Tile to world");
}
if($tile->getLevel() !== $this){
throw new LevelException("Invalid Tile level");
throw new LevelException("Invalid Tile world");
}
$chunkX = $tile->getFloorX() >> 4;
@ -2757,7 +2770,7 @@ class Level implements ChunkManager, Metadatable{
*/
public function removeTile(Tile $tile){
if($tile->getLevel() !== $this){
throw new LevelException("Invalid Tile level");
throw new LevelException("Invalid Tile world");
}
unset($this->tiles[$tile->getId()], $this->updateTiles[$tile->getId()]);
@ -2893,7 +2906,12 @@ class Level implements ChunkManager, Metadatable{
if($trySave and $this->getAutoSave() and $chunk->isGenerated()){
if($chunk->hasChanged() or count($chunk->getTiles()) > 0 or count($chunk->getSavableEntities()) > 0){
$this->provider->saveChunk($chunk);
$this->timings->syncChunkSaveTimer->startTiming();
try{
$this->provider->saveChunk($chunk);
}finally{
$this->timings->syncChunkSaveTimer->stopTiming();
}
}
}
@ -3089,35 +3107,31 @@ class Level implements ChunkManager, Metadatable{
if(isset($this->chunkPopulationQueue[$index = Level::chunkHash($x, $z)]) or (count($this->chunkPopulationQueue) >= $this->chunkPopulationQueueSize and !$force)){
return false;
}
for($xx = -1; $xx <= 1; ++$xx){
for($zz = -1; $zz <= 1; ++$zz){
if(isset($this->chunkPopulationLock[Level::chunkHash($x + $xx, $z + $zz)])){
return false;
}
}
}
$chunk = $this->getChunk($x, $z, true);
if(!$chunk->isPopulated()){
Timings::$populationTimer->startTiming();
$populate = true;
$this->chunkPopulationQueue[$index] = true;
for($xx = -1; $xx <= 1; ++$xx){
for($zz = -1; $zz <= 1; ++$zz){
if(isset($this->chunkPopulationLock[Level::chunkHash($x + $xx, $z + $zz)])){
$populate = false;
break;
}
$this->chunkPopulationLock[Level::chunkHash($x + $xx, $z + $zz)] = true;
}
}
if($populate){
$this->chunkPopulationQueue[$index] = true;
for($xx = -1; $xx <= 1; ++$xx){
for($zz = -1; $zz <= 1; ++$zz){
$this->chunkPopulationLock[Level::chunkHash($x + $xx, $z + $zz)] = true;
}
}
$task = new PopulationTask($this, $chunk);
$workerId = $this->server->getAsyncPool()->selectWorker();
if(!isset($this->generatorRegisteredWorkers[$workerId])){
$this->registerGeneratorToWorker($workerId);
}
$this->server->getAsyncPool()->submitTaskToWorker($task, $workerId);
$task = new PopulationTask($this, $chunk);
$workerId = $this->server->getAsyncPool()->selectWorker();
if(!isset($this->generatorRegisteredWorkers[$workerId])){
$this->registerGeneratorToWorker($workerId);
}
$this->server->getAsyncPool()->submitTaskToWorker($task, $workerId);
Timings::$populationTimer->stopTiming();
return false;

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