if the worker selected previously had a generator registered, but has since been shutdown, the workerStartHook that cleans up generatorRegisteredWorkers won't yet have been called.
This results in the worker being started by the submission of PopulationTask, and the generator doesn't get preemptively registered.
this fixes a bug I encountered when accidentally pressing ctrl+a+d (which inserts a chr(1) character), because it made the server unable to find the command - but still reported an error containing what looked like a valid command (character isn't printable).
if this happened, the index would stay set in activeChunkPopulationTasks, eventually causing the generation queue to jam up completely and non-forced generation to come to a standstill.
When profiling this, I noticed that we spend a stupidly large amount of time creating useless Position objects in the case of update=true, because Vector3->sides() calls Position->getSide(), which calls Position::fromObject(parent::getSide()). This is stupid because the update logic doesn't require Positions anywhere (as evidenced by this change needing no other alterations.
A rough profile shows that this improves setBlock() performance by about 25% in the update=true case, which is a pretty big margin.
As an added bonus, it gets rid of some unrealized cyclic dependencies in World->changedBlocks.
it doesn't serve any practical purpose to keep these separated, particularly since it's getting so difficult to figure out which errors are coming from which levels (since we always use 9, it doesn't really make any difference).
if the request/cancel/re-request happens all in the time before the queue gets drained, chunk hashes may appear multiple times in the queue. We don't want to process them twice if this happens (although it's mostly harmless anyway).
this can happen especially on large render distances when flying fast and changing direction - we decide we don't want the chunk, then, after changing direction and re-ordering chunks, we decide we do want it again, and end up registering a second callback. In this case, we need to ensure that only one of the callbacks gets executed (it doesn't matter which one).
this could happen if a plugin calls setPopulated(true) on a chunk after a request for its population landed in the queue, but before it actually got processed. In that case, the promise would never get fulfilled.
this does not indicate a failure; it indicates that the chunk has already been successfully populated.
In this case, we shouldn't be putting the task back on the queue.
This is skirting around the real bug, which is that requestChunkPopulation() doesn't check if the target chunk is already populated before it creates a new promise that it will be.
This reverts commit 866020dfdb.
For some fucking reason this broke resending chunks in some cases (and
sending chunks at all in others). I don't have time to debug this right
now, so it's going to have to remain broken, infuriatingly enough.
this allows chunks locked for population to be modified. If the PopulationTask detects that the chunk was modified during the onCompletion(), the result of the population will be discarded and rescheduled, so that it includes user modifications.
Player->showPlayer() assumes that spawnTo() will take care of all the checks necessary to ensure we don't actually spawn a player to someone it shouldn't be able to see. In PM3, there's nothing we can do about that.
This could be a problem if anything decides to override spawnTo() to do additional stuff and assumes that the function will always succeed; however, there's not much reason to do that (plugins sending packets should override sendSpawnPacket() instead).
this should never be hit in the PM case, but it's an InvalidArgument rather than AssumptionFailedError because plugins can and do call this with bad things.
to be consistent with Position::__construct() and Location::fromObject() (although Location::fromObject() has no choice, thanks to the anti-feature known as late static binding ...)
I did consider allowing yaw/pitch to remain optional, but considering the implicit immutability of Location, it really doesn't make any sense to create a Location with default yaw/pitch - just create a Position in that case instead.
tiles may be deleted in the following circumstances:
1) the target block in the new chunk doesn't expect a tile
2) the target block in the new chunk expects a different type of tile (responsibility of the plugin developer to create the new tile)
3) there's already a tile in the target chunk which conflicts with the old one
In all other cases, the tile will be transferred.
This resolves a large number of unintentional bugs caused by world editors replacing chunks without setting the deleteTilesAndEntities parameter to false (even the core itself does it).
closes#4520
entities exist completely independently from chunks now, so there is no need to interact with them whatsoever.
As I wrote in #4520, there's no sense in deleting entities here, since a chunk replacement is essentially just a mass block update.
On that theme, it might be a good idea to call Entity->onNearbyBlockChange() for all entities in the target and adjacent chunks when replacing a chunk, to ensure that they get the proper movement updates.
This reverts commit a5418a019d.
The more I assessed this, the more I realized that this implementation
doesn't actually offer any value. Since modcounters don't persist after
chunk unload + reload, they can't be reliably used to detect changes in
chunks without additional event subscriptions.
For the purpose I actually intended to use them for (population task
cancellation) there's a) another solution, and b) modcounts are
unreliable for that too, because of the aforementioned potential for
chunks to get unloaded and reloaded.
For the case of detecting dirty chunks within PopulationTask itself,
they are also unnecessary, since the dirty flags are sufficient within
there, since FastChunkSerializer doesn't copy dirty flags.
In conclusion, this was a misbegotten addition with little real value,
but does impact performance in hot paths.
in the normal case, all sessions will share the same PacketSerializerContext and Compressor, so this code will be the same as before
However, for the multi-protocol hackers out there, this should reduce the maintenance burden (@Driesboy) since now only the PacketSerializerContext needs to be maintained. I recommend a separate PacketSerializerContext for each protocol (perhaps put the protocol version in the serializer context too, if you need it for some reason).
back when this was just hardcoded >> 4 everywhere, nobody thought anything of it, but now it uses constants, it's easy to cross-reference and see where the duplicates are.
setPopulated() sets dirty flags on the chunk, causing the autosave sweep
to think they've been changed when they haven't. We now pass
terrainPopulated to the constructor to avoid this ambiguity recurring in
the future.
setGenerated/setPopulated and friends set hasChanged = true, which causes the world to autosave them the first time around, even though they weren't modified.
making this nullable was based on the invalid assumption that global sounds have no position, but it turns out they _do_ still use the position to make the sound come from the correct direction.
loadPlugins() is now the preferred option, since it does all the proper checks.
In addition, the server now acknowledges that loading a single plugin may cause multiple plugins to be loaded, so returning only a single Plugin is not representative of what's actually happening.
loadPlugins() is now a superior option to loadPlugin(), since it enforces dependency checks and also supports automatic loading of plugins when new loaders are installed.
Given the various limitations and flexibilities posed by EntityItemPickupEvent, I settled on this as the simplest way to deal with the problem.
- EntityItemPickupEvent may have its destination inventory changed, so we can't cache the result of getAddableItemQuantity() to use after the event.
- The item itself may have changed, so even if we thought we could add some items before the change, we might not be able to afterwards.
Considering the above facts, it's better to just give the whole itemstack to EntityItemPickupEvent, and let plugins use getAddableItemQuantity() on their own to decide if their chosen inventory can accommodate the item or not.
If it can't, then we'll just drop it on the ground.
This also fixes a potential issue where plugins changing the item to a custom one might end up with their items and the actual items both just vanishing if the target inventory was full.
closes#4499
it's not worth this turning into compatibility baggage just so that we can parse plugin_list.yml, especially when we have new ways to handle data parsing coming in the pipeline.
For something as small as plugin_list.yml, it's easier (and in this case better too) to just validate it manually (respect/validation was anyway too strict considering it's YAML we're dealing with).
for some reason we were reading and parsing the plugin.yml at least twice for every plugin loaded.
We were repeating work already done by the initial loadPlugins() triage (discovering correct loader, loading plugin.yml from disk, parsing plugin.yml, validating plugin.yml) every time loadPlugin() was called with that plugin.
PHPStan failed on 7.4 after updating to 0.12.99, and I figured it was less hassle to just do this than fix the build. In any case, we stopped shipping 7.4 months ago, and warned at 3.22 release that 7.4 support would soon be dropped.
this was originally worked around by 47f7af6739. However, that commit was just duct tape, and I never bothered to investigate if the config was being checked somewhere else.
Here's to a years-old bug finally getting fixed.
this could lead to harmful results, e.g. if a developer typo'd while writing the plugin.yml, an admin-only command could become accessible to everyone, since commands are by default accessible by everyone.
if the NBT is bogus for some reason
in PM3, these kinds of bugs wouldn't show up until/unless the item NBT was actually used, but on PM4, we decode it ahead of time, so the errors always show up immediately.
since taskkill is a subprocess of the server process, it gets included in taskkill's own attempted killing spree, but taskkill (wisely) won't kill itself.
Sacrifice dynamic composer autoloader path to do this, because we don't
need it anyway - it was a misconceived feature from the days when I used
the same workspace for PM3 and PM4 both.
while annoying, PHPStan is right to complain about this, because putBool() is impure, meaning that these fields could have been mutated in the call.
We know they didn't, but PHPStan doesn't, and we can't mark the method as pure because .. well .. it isn't.
this unpleasantly-named method allows controlling the source-forming behaviour of liquids by changing the required number of adjacent sources that must be present in order for a new source to form. This allows stuff like non-infinite water.
in PM4, all blockupdates are buffered, so the old 7x performance penalty that used to be incurred by doing this is no longer a problem.
Also, this actually reduces the overhead of explosions themselves by moving the onNearbyBlockChange() burden off explodeB() and into the main world ticking function.
isChunkGenerated() merely checks if the chunk can be loaded from disk, if it's not in the runtime cache already.
This is pointless in all of these cases, because the check is prefaced by an isChunkLoaded() check, which already limits the possibility anyway. If the chunk is not generated, it'll also be considered not loaded.
this raises false-positives during shutdown if players were online.
The fact that the player entity leans on the World to clean up after it is slightly problematic, but I'm not sure what else to do about it for now.
this allows entities to exist outside of generated chunks, with one caveat: they won't be saved in such cases.
Obviously, for player entities, this doesn't matter.
fixes#3947
this fixes 2 problems:
1) Blocks which set themselves to something else during onNearbyBlockChange() would not receive any block update
2) A memory leak when blocks in unloaded chunks were scheduled for an update.
I'm a little uneasy about this change, because there must have been some reason why I put this at the end of the block and not at the start, but whatever it is, I can't reason about it, and there's reasons not to put it at the end too.
the only reason to use getCollidingEntities() instead of getNearbyEntities() is if you have an entity that may or may not be collidable depending on certain conditions.
Really, I don't think this logic belongs in World at all, but for now it has to stay, because some other stuff depends on it.
these two methods are very misleadingly named, but they do almost exactly the same thing - the only difference is that getCollidingEntities() does a couple of additional checks.
we can't have landed on it unless it actually has a collision box - otherwise, we only landed _in_ it.
This assumes, of course, that no blocks have bounding boxes >= 2 blocks tall, which currently none do.
instead, just ungate this and allow the provider to decide what to do.
Any chunk that contains entities or tiles is already always considered dirty, so the only thing the flags are good for is flagging chunks that previously had tiles and/or entities but no longer do.
In those cases, it's just removing keys from LevelDB anyway, so it's already very cheap.
Avoiding these redundant deletions is not worth the extra complexity and fragility of relying on flags to track this stuff.
this was using json before, which is horribly inefficient.
This saved about 200 KB of memory on initial startup (which isn't much, but for more complex recipes, it might have been significantly worse.
the use case for this is basically zero, since the community prefers implementing their own subcommand systems instead (which are much more flexible).
In addition, allowing spaces in command names makes it extra complicated to display helpful information to the user, such as the command that was actually accepted by the command map (which would be useful for identifying accidental invisible characters / control characters when sending commands).
This event is currently fired for tree and bamboo growth. Its intended use is for any plant growth that affects multiple blocks at once.
TODO: We could explore using this for cacti and sugarcane?
this makes just about everything easily accessible via commands.
There are some stuff that shouldn't be here due to not being actual items (e.g. door blocks, bed blocks, wall coral fans) but since there were legacy aliases for all those things already, I figured what the heck - it's more effort to exclude them, so whatever.
this isn't specced up with some of the finer features of LegacyStringToItemParser such as metadata parsing, but those are still a work in progress (and probably limited to specific items like durable stuff).
The goal is to unbind these aliases from legacy internal IDs, while also providing a nice flexible way for plugins to add their own items and aliases to the existing system.
This system allows mapping a string to any item at all, irrespective of state, internal IDs, or any of that nonsense. This means it's finally possible to have stuff like lapis_lazuli and bone_meal aliases in commands.
The rationale here is that inventories don't actually pick items up - their holders do.
It's especially misleading to say that an inventory is picking up an item in creative mode when the picked-up item can't actually be added to the target inventory in the first place.
This change allows a range of new functionality, such as:
- Allowing survival players to pick items up even when their inventories are full, similarly to creative players
- Changing the destination inventory of collected items (e.g. items could be redirected to the offhand or ender chest inventory, while still allowing other plugins to understand what's happening)
As an added bonus, this obsoletes one more use case for Inventory->getHolder(), bringing us one step closer to removing the cyclic reference nightmare from inventories.
The choice of naming (EntityItemPickup, instead of EntityPickupItem) is to be consistent with other events, where the word order is SubjectObjectActionEvent.
these weren't getting corrected since php-cs-fixer 3.0 due to a change in the default configuration for native_function_invocation. Since the builds are randomly choosing to use php-cs-fixer 2.19 at the moment, the consistency is a problem.
%prefixes should only be necessary for embedded translations where the key isn't at the start of the string.
Longer term we should just drop raw string translation entirely and just translate Translatables exclusively, but this is a stepping stone.
this is a far stretch, since the documentation doesn't mention that the string needs to be tokenized. Anyone passing an array in here is most likely doing so by mistake.
this is a far stretch, since the documentation doesn't mention that the string needs to be tokenized. Anyone passing an array in here is most likely doing so by mistake.
this is not used in the PM core, and is only used by 1 plugin in the whole public ecosystem: BigBrother. It makes more sense to make BigBrother maintainers shoulder the responsibility of maintaining this code, since they are the only ones that need it - besides, if this changed in any MCJE update in the last 5y, nobody has updated it, and nobody has maintained it either due to not having a fucking clue what the thing is for (the documentation is basically nonexistent).
this makes translation usage much more statically analysable.
The only places this isn't used are:
- places that prefix translations with colours (those are still a problem)
- places where server/client translations don't match (e.g. gameMode.changed accepts different parameters in vanilla than in PM)
this also fixes use cases like:
[1] = something;
[0] = match(...)
It made no sense whatsoever to discard the keys anyway.
Language::translateString() already supported named parameters since
forever anyway.
I was never able to reproduce this, but it appears that Windows breaks the character encoding of command parameters (and also unicode environment variables, even though UNICODE_ENVIRONMENT should be set in php-src) when the file path contains Unicode characters (such as Cyrillic).
We workaround this problem using base64, which is an abysmally shitty hack, but not worse than using a subprocess for ConsoleReader in the first place. PHP fucking sucks, and so does Windows.
closes#4353
I moved these to a trait in anticipation of having multiple full Inventory implementations. That's no longer necessary because of the abstraction of SimpleInventory.
this happens if the parent process is killed via SIGINT, because its stdin will be closed, interrupting a blocking read. This might also happen if the user pressed CTRL+D, so we don't die unless end of socket stream was also detected.
closes#4335
This brings a significant performance improvement to login sequence handling, reducing CPU cost of `PrepareEncryptionTask` by over 90% and `ProcessLoginTask` by over 60%. It also allows us to shed a dependency.
while it's true that you might be able to skip the CPU waste from verifying a player's login just to find out that they are banned, this is generally a minority case anyway, so it doesn't make a lot of difference overall. This additional note is essentially a recommendation premature optimisation, which will likely lead to people making security mistakes.
this gains a very small performance improvement by avoiding unnecessary !== null checks on every packet written in either direction. It's insignificant for sure, but I just found this code in an old stash, so what the heck.
the reason there hasn't been any API until now is because of how inconvenient it was to expose a LSP-compliant API _and_ use the same base class for handling all the connection logic. This commit fixes that problem by abstracting shape handling away from BaseRail entirely, so that now it deals exclusively with connections. Deciding the shape of rail to use is now the job of the subclasses.
this will break non-standard use cases with large forces, but they only have to stick a 'null' at the end of the parameter list.
Since this function should be primarily used for vanilla knockback, it makes more sense to keep the default as vanilla, but allow people to change it if they want to.
closes#4106 (this is close to #4106 anyway, but small enough that it was easier to recreate it than pull and modify it)
closes#2707
this doesn't implement the server-side logic for the "stickiness" (slowdown) because we don't have the system needed for it yet.
It also doesn't have parity with vanilla on the damage.
SingletonTrait is pointless here for multiple reasons:
1) the class is final
2) this is protocol-specific translation of types, no loss of data or alternative mutation of it needs to occur
Using SingletonTrait is an obstacle to separating the protocol library from the core code, so it has to go.
while this is a bit hacky outside of the protocol namespace, it makes it much easier to use the protocol library for alternative purposes, such as for a client or MITM proxy.
It also removes all but one remaining core dependency of the protocol library, making it very close to being able to be separated from the server core entirely.
WorldProviders now have the following requirements removed:
- __construct() is no longer required to have a specific signature
- static isValid() no longer needs to be implemented (you will still need it for registering, but it can be declared anywhere now)
- static generate() no longer needs to be implemented
This paves the way for more interesting types of world providers that use something other than local disk to store chunks (e.g. a mysql database).
WorldProviderManager no longer accepts class-string<WorldProvider>. Instead, WorldProviderManagerEntry is required, with 2 or 3 callbacks:
- ReadOnlyWorldProviderManager must provide a callback for isValid, and a callback for fromPath
- WritableWorldProviderManagerEntry must provide the same, and also a generate() callback
In practice, this requires zero changes to the WorldProviders themselves, since a WorldProviderManagerEntry can be created like this:
`new WritableWorldProviderManagerEntry(\Closure::fromCallable([LevelDB::class, 'isValid']), fn(string ) => new LevelDB(), \Closure::fromCallable([LevelDB::class, 'generate']))`
This provides identical functionality to before for the provider itself; only registration is changed.
this implementation is working, although incomplete:
- The shulker close sound should not be played until the end of the shulker closing animation, which takes approximately 1 second.
- An open shulker box has a different collision box than a closed one - it should be +0.5 in whichever direction the shulker is facing. (During the animation, the bounding box also dynamically changes size - you can see this in vanilla by shooting an arrow into the top of an open shulkerbox facing UP, and then closing it - the arrow will fall and collide with the lid multiple times.
However, resolving both of these issues requires significant internal changes which are beyond the scope of this PR.
the intent of these hacks was to break cyclic references to avoid having objects lingering in memory. However, all of the stuff that's being removed in this commit no longer has any effect anyway, due to the fact that these things don't circularly reference each other anymore. Notably, Tile inventories now keep Position instead of a Tile ref.
This reverts commit 9b52af62b6.
We shouldn't assume that a string maps directly to a legacy ID,
because we might want string aliases (e.g. dark_oak_boat) which refer to
items that have a specific meta value in the MCPE system.
Overall, I want to get rid of the reliance on IDs here and register all
this stuff using closure callbacks on VanillaItems, so getting rid of
this assumption also serves that goal.
it's better to just implement this for stuff where there's explicitly designated aliases, otherwise we could end up with unexpected BC breaks (e.g. hardcoding POSTWORLD in plugin.yml would suddenly break if the core enum was changed, even though it remained valid).
this makes more sense overall from a reader's perspective.
and also provide a rug-jerk for any idiots using World->close() when they aren't supposed to? ....
this stuff has different functionality than everything else in the
command namespace (specifically console handling), so it doesn't belong
in here.
I know that this will probably break some plugins, but I don't care,
because plugins shouldn't have been abusing ConsoleCommandSender in the
first place.
this occurred because of transactions arriving before MobEquipmentPacket updating the player's own held item slot. This was only a problem while rapidly changing hotbar slots and simultaneously using items, like projectiles.
closes#4168
this is necessary to get rid of the broadcast permission callbacks, which retain references to the Player itself, forming a cycle which would prevent PermissibleBase->__destruct() from cleaning up.
since MCPE-19214 still hasn't been fixed after all these years, it's safe to say they won't fix it in the near future, and this causes placement glitches in PM.
since we write these into a transaction instead of actually modifying the world directly, we can use the transaction to verify that the placement location is OK before setting the blocks.
closes#4248
instead, use a const array of the offsets and add them to the coordinates, which avoids the allocations.
In synthetic benchmarks, this method takes 40-50% less CPU time by eliding ZEND_INIT_ARRAY and ZEND_ADD_ARRAY opcodes. In practice, the benefit will likely be much smaller (perhaps even irrelevant).
this can fail if the backups directory points to a different drive than the original worlds location. In this case, we have to copy and delete the files instead, which is much slower, but works.
I REALLY advise against putting backups on a different mount point than worlds if you plan to convert large worlds.
phpstan doesn't report these because .. reasons .. @ondrejmirtes this is causing bugs to go unfound :(
I'm aware of the irony that I just silenced the bugs that were exposed by this commit .. that's an architectural problem for another day
despite MCPE claiming to use GCM, it omits the auth tag, which defeats the whole point of using GCM.
CTR can be used instead, with the final 4 bytes of the IV being 0002.
7.3 isn't actively tested anymore, and since 7.4 has been out for so long already, it doesn't make sense to keep pandering to users who can't be bothered to update their PHP binaries.
In most cases, these users are also experiencing problems caused by older versions of pthreads that were long since fixed.
In addition, pthreads is no longer tested or supported on 7.3, so users can't get newer bug fixes even if they wanted to.
this interface is just about the most pointless code in all of PM or Bukkit. In over 4 million lines of code on Poggit, a Google search and a GitHub search, I didn't find a single usage of it that wasn't just bukkit internals code copy pasta, a spoon, a port of PM/Bukkit/whatever into a different language, or someone's generated javadoc.
Worker::isRunning() returns false after it exits the run() function, even if tasks are stacked and it isn't shutdown.
While this is mostly harmless (since the internal destructor will join the thread anyway), this should be fixed anyway.
these all had to be updated in tandem because of the dependency tree - RakLib, RakLibIpc and NBT -> BinaryUtils, RakLib and LogPthreads -> Log, RakLibIpc -> RakLib.
preset is now supported as its own key, and it's less confusing to present it separately, since that's how it's displayed in the server.properties also.
the following things are changed:
- Player->getSpawn() no longer returns a safe spawn by default. Instead, if the player doesn't have a spawn set, it returns the world's stored spawn directly. This allows consistent behaviour of locating safe respawn positions without double calculation of safe spawn position, and also fixes crash issues during the login sequence if the player's spawn position referred to ungenerated terrain.
- Player->respawn() is now asynchronous, using the promise returned by orderChunkPopulation() to complete respawn after the terrain is generated. This allows consistently selecting a safe respawn position and fixes crashes when respawning if the spawn location was in ungenerated terrain.
There remains a problem that ragequit respawns are still only handled right after PlayerJoinEvent, which leads to the original spawn terrain being sent to the player, which is obviously very wasteful. However, that's a problem for a later commit.
when a chunk population is ordered, its only chunk loader is the one that the World installed to keep the chunk loaded while it was generated. So, when the resolver removes its chunk loader from the chunk, it triggers the chunk unloading mechanism, which causes the promise to directly be rejected.
previously, these were forced to extend BaseInventory because of the amount of crap in Inventory's interface.
This meant that these inventories had their own slots storage, which would be _mostly_ unused because these inventories aren't real inventories, but rather just delegates.
This lead to a variety of bugs in the past, such as certain API methods on BaseInventory not working correctly for DoubleChestInventory in particular.
Now, BaseInventory just implements the functional part of the inventory implementation, leaving the storage system up to the implementation.
A SimpleInventory class is provided with a simple SplFixedArray storage backing, which is used by most inventories.
EnderChestInventory and DoubleChestInventory now extend BaseInventory directly, and implement custom methods for dealing with their delegates.
closes#3461
literally every other particle/sound has the subject first, followed by the (optional) verb, and finally Particle (or Sound).
In addition, we refer to breaking blocks as 'break' everywhere except here, where we refer to it as 'destroy'.
now, EnderChestInventory is just a temporary window, much like anvil/enchanting windows. It provides a gateway to the player's PlayerEnderInventory.
This removes one of the remaining obstacles to disallowing null World in Position constructor.
signs now become finalized if:
- the player quits and rejoins (because the entity runtime ID of the player will not be the same)
- the chunk is unloaded and reloaded (because the tagged entity runtime ID is not saved).
closes#4198
this isn't practical to fully implement right now due to limitations
imposed by the legacy shitfest system we're using. To make stripped
dynamic, we would need to switch the IDs _and_ variant info dynamically,
and I have no idea what bizarre side effects that might have.
setRotation() is conditionally useless, but there's not much we can do about this right now; and exposing it like this is better than having plugins interacting with tiles.
* Allow plugins to use PSR-4 namespace mapping
this is a reduced implementation which serves the 99% use case without being horribly breakable.
Plugins may now specify a `src-namespace-prefix`, which should be set to the namespace of the classes in `src`.
If the old system is used, `src-namespace-prefix` can be omitted, or set to an empty string.
Examples:
- If `src-namespace-prefix` is `dktapps\test`, `dktapps\test\Main` will be searched for in `src/Main.php`, instead of `src/dktapps/test/Main.php`.
* Migrate TesterPlugin to PSR-4
it's not the protocol implementation's job to decide what's garbage. It should only indicate that a packet MAY be sent by the client. It should then be up to the handler to decide what to do with it.
the commit I reverted put the preconditions in the completion handler,
which is executed AFTER THE CHUNK IS SENT.
Revert "NetworkSession: allow Player to handle its own business in chunk sending"
This reverts commit a223d1cbf3.
because of the shitty way that the chunk resending is handled, it causes all kinds of problems with the async system because of potential reversions of the state during the process.
this implementation is very rough due to having to hack around lots more MCPE bullshit, and currently doesn't allow dynamic coral types; but it's there. We'll clean this up after 1.13 migration is done.
for some reason putting NBT on some items makes the creative inventory go haywire. Sadly, we currently need this hack, so I limit it to only stuff which actually needs it (blockitems).
closes#4159
this is slightly slower, but saves a significant amount of memory (~80 KB per chunk).
Since ext-chunkutils2 doesn't do copy-on-write trickery like the PHP impl did, we need this to get the memory advantages back.
3 is absurdly small. 8 is a more realistic estimation of what the average player's render distance will be (it's also the default server.properties limit).
3 doesn't even fill the default spawn-radius setting, meaning that delays during player connection would occur anyway due to generation.
this makes PermissionAttachment more and more like Permission, except that it doesn't have a name.
Right now, the only value of this API change is that it allows breaking references to dead Permissibles, but in the future it should be possible to reuse a single PermissionAttachment on multiple Permissibles.
since a while ago, we're anyway just discarding the internal buffer anyway when the packet is repeatedly encoded, so this doesn't serve any advantage anymore.
We do need a system to be able to reuse encoded packet buffers, but right now we're not reusing them anyway.
-1 is a PM-specific thing. Right now there is a hack in the NetworkBinaryStream which prevents this from becoming a problem, but that might not be the case in future.
we can't get the safe spawn location of a set of coordinates if the coordinates are in an ungenerated chunk. This can happen if doing /setworldspawn <somewhere ungenerated> and then having a new player join the server.
this can fire while the player has the inventory window open, because it also gets sent when the player swaps their held itemstack for something new.
We already had a special-case for mouseover with entity ID 0, but since
this isn't just a zero problem, a more general fix suits better
(particularly since we might need to handle the 0 case anyway).
closes#4140closes#4141
If allowFlight was toggled by the server (e.g. due to gamemode change), a race could occur due to network latency where the client could try to enable flight, and then get kicked for cheating.
Since this can happen in legitimate, non-cheating cases, we can't make any assumptions about whether a player is cheating, so instead we just revert it, like we do with every other bad input.
the notify() to flush the buffer might arrive in between the writeLogStream() and synchronized() calls in the thread body, resulting in a deadlock if the logger thread managed to call wait() before the main thread did.
Plugin is the interface by which the server core interacts with plugins, so it should be limited only to the stuff that the server actually uses.
These methods are still provided by PluginBase, so in 99.9% of cases there will be no BC break.
This reverts commit cb06be615a.
we can't push this to stable because it would break plugins without any
way to know (no protocol or API change).
At most, this should have been wrapped into a protocol change.
while stream_select() doesn't work on pipes, if it ever starts working properly in the future, we'll need this code. In the meantime, it's harmless (it just immediately returns 1 anyway).
closes#4069
this happens because the client bans any server that has an invalid pong, which is very stupid in this case because the gamemode isn't even shown on the UI anyway ...
this is not a complete changeset, but it's sufficient to get servers back online.
There are additional changes to PlayerAuthInputPacket which need to be reversed.
we check if an existing player is online with a matching XUID first; if there isn't, we don't bother loading the playerdata, since that other player couldn't have joined unless they had a match or were allowed to bypass.
mushroom stem (and all-sided stem) are unique blocks, which don't drop anything and which don't stack with other shroom variants when block-picked.
They also get mapped to the same block when placed, and there's no distinction between red mushroom stem and brown mushroom stem.
when using VanillaBlocks::CHISELED_QUARTZ(), VanillaBlocks::PURPUR_PILLAR() or VanillaBlocks::QUARTZ_PILLAR(), static analysis was unable to detect getAxis() and setAxis(), because these blocks were implemented using anonymous classes.
detector rail has fundamentally different functionality than activator and powered rails, so it's misleading to present the same APIs for both.
detector rail's 'powered' state is better referred to as 'activated', since it means the detector rail is actually _producing_ power, and not _receiving_ power.
because of the way async tasks are processed, we might collect results from a task before it's able to be collected by collect(). Therefore, the queue might be empty, even though there are still tasks to be collected.
this avoids needing to call Terminal::init() before starting a MainLogger. Since it inits the formatting codes anyway when log messages are first recorded, it shouldn't be necessary to pre-initialize it.
this resulted in a deadlock in https://github.com/pmmp/PocketMine-MP/runs/1831812620?check_suite_focus=true because the notify() arrived while writeLogStream() was executing.
This ensures that either:
- the notification will occur before the sleep, and therefore no sleeping will occur (this->shutdown = true before the wait)
- the notification will arrive during the sleep.
we can't safely use `ubuntu-latest` because the build caches will break if they were built for 18.04 and used on 20.04, or vice versa. Instead, we pin the images (and caches) to a specific version.
Player->useHeldItem() assumes that if the old item == the new item, we want to set the item back into the inventory if it's modified in-place. Therefore, we don't modify the item in-place to bypass the problem.
closes#4022
variadics are a bad fit for this because what we really need is to accept callable with any number of arguments. LSP requires that the provided number of arguments must be >= than the required number of arguments.
clickPos is relative to the base block position, so if you keep aiming at the same spot on the block and jump, it thinks you're still spamming.
closes#2730
we don't need to scan the parent classes for anything other than private properties, because protected and public properties will appear on the main reflection as if they were declared directly as such.
this provides some performance improvement (although it's difficult to measure because of cache).
this does mean that we read some garbage data during chunk reads, but it's less costly than hitting the disk twice.
I was unaware that fseek actually makes a syscall which is rather costly, which became painfully obvious during large world conversions on PM4.
On average this problem appeared to be adding about 5ms to the load time for a newly loaded region, which is insanely expensive.
originally I introduced this to make it easier to implement the various APIs addPattern removePattern etc, but those were later removed in favour of simple getPatterns() and setPatterns(), allowing plugin developers to use ext-ds APIs to manipulate patterns.
However, ds poses a number of headaches because of mutability combined with by-ref semantics, which make it a pain to use these on the APIs because we can't guarantee that they won't be modified.
As much as arrays suck, they have two significant advantages over ext-ds: 1) they have copy-on-write semantics, and 2) they support PHP 8.0 without any extra work from me.
this allows plugins to request this data whenever they want it (e.g. to save offline any time they want, instead of being confined to the server autosave interval).
this exception is only thrown if the player is closed, which is already unexpected in the first place and will actually crash if it's not kosher. This prevents doing stuff like saving players during onDispose(), which crashes the server if a player is disconnected due to flagForDespawn().
In the old days, we used to try to correct this problem by adjusting the region header to match the
length found at the start of the chunk payload. However, this has a very good chance to cause corruption
of other chunks, since we can't do any fast overlap checks (an upsize might cause the chunk's alloocated
area to overlap into another one, causing corruption when either chunk's space gets written to).
This corruption risk has become more problematic since the
introduction of region garbage sector reuse, since a broken location
header could cause chunks to trash each others' saved data.
In addition, if there is a length mismatch, there's a good chance that the oversized chunk itself will
already be corrupted, so we'd just fail trying to decompress it later on.
So, instead of trying to fix this automatically, we bail and hope this doesn't occur often enough for
users to get upset, and allow external offline tools to attempt to repair the mess instead.
requestChunkPopulation() respects the queue size, orderChunkPopulation() does not.
requestChunkPopulation() should be used for non-essential generation (which mainly includes generation for player use).
orderChunkPopulation() should probably be used by plugins.
commit 1f42169f0f929958f7d68a68f194c6f3492b7eb4
Author: Dylan K. Taylor <odigiman@gmail.com>
Date: Mon Dec 14 21:23:44 2020 +0000
... install it in the right fucking place
commit d2a88abeda5fa937d3f508c4e0300a949af97846
Author: Dylan K. Taylor <odigiman@gmail.com>
Date: Mon Dec 14 21:14:21 2020 +0000
Build PHP using system libraries to reduce rebuild time
the functionality of this API method is too specialized to be of any practical use.
In addition, a search on Poggit reveals that the only uses of this API method are abuses or incorrect uses anyway.
it's possible we could clean the path up to detect which plugin caused the crash, but for now I'll be happy to not have them showing up as core crashes ...
it's now the World's responsibility to manage adding/removing entities from appropriate chunks. Entities no longer know or care that chunks exist.
Entity->checkChunks() remains as-is for backwards compatibility - now it just calls the world to sync its position.
if a PopulationTask took place after the target worker was garbage collected, the population would fail and the chunks it used would be copied for nothing.
This change marks workers as having unregistered generators when detecting that a worker that previously had a generator registered is restarted.
a non-generated chunk is now always represented by NULL. This forces the case of ungenerated chunks to be handled by all code, which is necessary because ungenerated chunks cannot be interacted with or modified in any meaningful way.
in cases like PopulationTask it makes more sense to store the coordinates separately where they can be stored more efficiently (once instead of 9 times)
In addition, PopulationTask shouldn't need to serialize an empty chunk just to copy coordinates.
I've made changes like this in other areas already in preparation for the day when chunks no longer contain their coordinates, so this brings us one step closer to that goal.
this only made sense to work around the server crashing when creating a player in ungenerated terrain, but spawning at y=256 is hardly preferable, and it'll crash since fd99445c5b anyway ...
previously this created an empty chunk for the entity to hang around in until the terrain was generated, but that's problematic for several reasons, most importantly the fact that non-generated chunks are not saved.
instead, it will fire when the chunk comes out of PopulationTask and is set into the world using setChunk().
There is still one place left where auto-creation of empty chunks is used by the core, and that's an issue i'm still deciding how to deal with.
I'm of two minds whether this should continue to fire onChunkChanged() on chunk loaders or not, since the chunks won't be referenced by any chunk loader anyway by virtue of not existing ...
this fixes#3906.
TimingsHandler will now be automatically destroyed when there are no TimingsRecord referencing it and its owner has no references left to it.
TimingsRecord will be automatically destroyed at the end of the timings session (if active).
This fixes records from temporary timers being lost after the timings handlers are removed, while also fixing TimingsHandlers piling up regardless of whether timings are running or not.
This opens the doors to have more volatile timers, such as per-player/per-session timers, which are destroyed on player quit, but which won't result in the timings disappearing from the final timings result.
regardless of how long an async task takes to run, it will take a multiple of 50ms to get the result processed. This delay causes issues in some cases for stuff like generation, which causes locking of adjacent chunks, and async packet compression, which experiences elevated latency because of this problem.
This is not an ideal solution for packet compression since it will cause the sleeper handler to get hammered, but since it's already getting hammered by every packet from RakLib, I don't think that's a big problem.
this gives a bit more control over how packets are broadcasted, which might be useful if the batch format changes (e.g. adding a length prefix) for multi version.
This really ought to be unique to a protocol context instead of a network interface, but for now this is the best we can do.
there is no longer such a thing as a permission granted to 'everyone', since we're no longer limited to true/false/op/notop, and regular players are now assigned the pocketmine.group.user permission.
It's possible we might want to add more restricted groups than 'user' in the future, in which case it would be behaviour-BC-breaking to change the default assigned permissions when creating a new PermissibleBase. Therefore, it's better to not assign any permissions at all and let the caller decide.
In addition, this solves the problem of implied permission subscriptions and leak on PermissibleBase construction - if base permissions are provided, it should be expected that the permissible will subscribe to those permissions.
this has the most reliable behaviour, because some stuff like respect/validation likes to include files unconditionally which declare functions that are already declared, which breaks due to the lack of function autoloading.
this was used for 2 things:
- to notify parent permissibles on recalculate permissions (not needed anymore thanks to callbacks)
- subscription to chat broadcast permissions (now handled separately, again using callbacks)
therefore, it's no longer needed for PermissibleBase to reference its parent, meaning that we can have one less circular dependency in our lives.
since the only way to obtain PermissionAttachmentInfo via the API is from the Permissible API, it makes zero sense to ask the attachmentinfo for its permissible, since we obviously already had it to be able to get the info in the first place. Therefore, this is just another useless reference stopping Permissibles from being garbage-collected.
lack of permission calculation means that child permissions might not have been set correctly, so this might lead to users being able to access things they aren't supposed to.
it also doesn't provide stuff like isOnline() (you had to have a Server reference to get an OfflinePlayer anyway, just ask the Server if the player is online ...) and getPlayer().
to obtain an OfflinePlayer instance you had to have a server instance to start with, which means getServer() is pointless, and also that isOp() and setOp() (which can be removed thanks to the fact that OfflinePlayer is not a Permissible) can be done by just asking the server.
relying on permission subscriptions for this was unreliable (a permissible is not always subscribed to a permission even when it does have it), and also difficult to control (for example there have been various bugs in the past where a Player ended up subscribed to broadcast permissions when it didn't expect to be, thanks to permission recalculation happening too early).
In addition, we might in the future want to have broadcast receivers which are not permissibles (i.e. a more general interface than CommandSender (why does a broadcast receiver need to also be a command sender, anyway?)), which the permission system wouldn't be suitable for.
for example, Player->recalculatePermissions() was not called when a player's op status changed, nor when a permission attachment altered permissions (potential secvuln for broadcasting).
these methods have better pathways through Server directly.
Also, setBanned() does not allow customising the reason for banning or the duration, nor does isBanned() account for IP bans because the code is so old ... better to force dependence on a central code path to avoid these inconsistencies.
I want to do the same thing for OP, but that's a separate problem due to its effects on the permission system.
this method has an explicit dependency on permission subscriptions, which I plan to eradicate.
The method's functionality can be replaced using Server->broadcastMessage() with a custom recipients array.
Bukkit CCC at its finest... what the fuck this was doing anyway I have no idea
an addChild() method would have made far more sense, especially considering that addParent() doesn't actually mutate the child.
it's now possible to cancel the banning by cancelling PlayerKickEvent.
In addition, the disconnect message will now properly explain why the player is banned instead of just saying 'You have been banned',
and also banned-players.txt will show 'Died in hardcore mode' as the reason instead of being completely blank (seriously, we couldn't tell the difference between real bans and hardcore bans????)
this is an impressively dumb idea.
the playerdata is not used here in any capacity so it doesn't make sense to load it, especially considering that it takes a significant amount of time.
I think we should probably get rid of this considering the potential for inconsistencies within a chunk, but not retaining this is a bug nonetheless, even though it doesn't have any effect in PM itself since we always use BlockLegacyIds << 4 as the empty block ID.
so, this is only really aiding (ab)use cases which weren't intended anyway ...
this better describes the purpose, which is to identify air.
though, it might make more sense to make air just always have zero as air's runtime ID, since this parameter is apparently making plugin devs think that this is suitable to fill a chunk with a specific block ...
closes#3907
this reduces the impact of compression on the login sequence by about 90%; however, since compression only accounted for about 30% of said overhead at most, it's not really a massive difference.
there are some complications with coral plants due to the fact we're stuck with R12 worlds right now - and also coral fans are a major pain to implement due to how messed up the metadata is.
longer term I want to rip this crap out completely, but right now this provides minor maintainability benefits, while also making it slightly less nasty to deal with other containers which animate their blocks, such as barrels and shulker boxes.
closes#3910
the existing naming was misleading, and many plugin devs assumed that it returns an exact match. However, this is not guaranteed, and it's possible for two different players to match the same prefix.
- There is no defined behaviour for what happens when multiple players can equally match a prefix (e.g. 'fr' could match 'fred' or 'frog' equally, because the name lengths are the same)
- A prefix might match a different player at a different time (e.g. 'fr' could match 'freddie' before 'fred' joins, after which it will match 'fred' instead)
With these flaws in mind, it's better to break compatibility on this to make the intent more clear, and to make plugin developers reassess their usages of this method. In most non-command use cases, they should likely be using getPlayerExact() instead.
we only ever need the first entry, so there's no point storing all of them. In addition, the field is private, which guarantees that nothing else needs the array either.
This also fixes phpstan/phpstan@c50650c5dd.
this reduces bandwidth efficiency because it can't be compressed with everything else this way. If we want to cache stuff sent during the login sequence, it's better to stuff a bunch of stuff into a batch (e.g. crafting, creative, actor ids, biome defs) and pre-compress that as one big package instead.
these types of chains would never normally occur, but they've been seen in the wild. Attempting to resolve such chains has exponentially increasing complexity.
this action (which is more accurately referred to as 'activate item' or 'use item' in other areas) always fires on right-click when holding any item, whether aiming at a block or not.
every time a chunk passed through Level->generateChunkCallback(), it fired onChunkChanged() for chunk listeners, which in turn caused players to rerun chunk orders even though the target chunk had not been sent yet anyway.
this allows injection of arbitrary ChunkManagers into a single Generator instance.
The objective here was to remove the requirement to cache a SimpleChunkManager instance in worker-local storage, because that requires that the chunks it stores be manually removed to avoid memory leaks. However, there are some other obstacles, primarily the worldHeight which is not retained anywhere else.
this caused some performance issues and silent bugs with the generator, notably that the generator would always think all chunks had been changed, causing them to be re-set back into the world 9 times.
instead of being forced to use the Server async pool
right now the intent of this is to reduce (and ultimately eliminate) the dependency of World on Server, but it might come in useful for other stuff too, for example a chunkserver-based generator implementation which blocks on network instead of eating CPU (it would just waste CPU for other tasks).
these methods are not used in hot paths and are inherently slow anyway, not to mention the introduction of morton codes eliminating the hashtable indexing problem.
this restores SimpleChunkManager's behaviour to PM3, removing the need for GeneratorChunkManager (although I'm dubious whether SubChunkExplorer makes any sense in there any more now that we have morton in the mix).
we might also need to delay this if any adjacent chunk is also not loaded, in case the block wants to access adjacent blocks during its neighbour update.
non-populated chunks shouldn't be light-populated anyway, but in some cases they are (bug or plugin interference).
chunks which were already populated might get modified by adjacent chunk populations, which should invalidate their lighting because generation doesn't track which blocks were changed, so the whole chunk should be recalculated.
when setBlockSkyLightArray/setBlockLightArray was used, currentLightArray would retain a reference to the old light array, which would cause false readings if SubChunkExplorer didn't move away from that subchunk and back.
This causes a small degradation of performance, but I think it can be implemented differently anyway.
This also fixes#3816.
previously a file with a 4-letter name ending in 'mca' in the region folder of a PMAnvil world would cause the world format to be unrecognized. This happens because strrpos() returns false when the substring isn't found, which gets coerced to 0 when used in addition.
this has a couple of side effects which need to be explored.
- first of all, this bug prevented generateLevel() from filling in the preset from server.properties. With this fix, worlds which don't have any extra generator settings will start to be generated using server.properties settings, which is almost certainly not expected behaviour.
- preset can now be specified separately from generator in pocketmine.yml, which is nicer for users.
this uses the unused bits on the Y component to expand the X/Z axes to 2^27 blocks long instead of 2^21 permitted by a regular morton3d code. It does require the sacrifice of an additional bit on the Y axis, but the performance advantages are more than worth it.
I'm exploring how realistic it would be to just eliminate blockHash global usage (currently in lighting updates and explosions). This would allow scaling up to 2^32 without larger hashes (morton2d for chunks).
this allows plugins (and maybe later on the core) to detect async worker overload and warn the user about potential performance issues.
I planned to implement such detection in the core directly, but it turned out to be a bit more complex than I anticipated. At the least, this API might be useful to someone else.
literally nobody uses this. I don't think anyone even knows it exists.
It's also an obstacle to separating event handler registration from PluginManager.
Previously, upwards movement wouldn't be considered, but downwards would, so if an entity bobbed up and down in the air for a while (e.g. while being comboed in PvP), the downwards distance would accumulate and deal a large amount of fall damage on touchdown.
This commit changes fall distance measurement to correctly account for upwards movement.
A better way of measuring fall distance would simply be to record the highest Y coordinate reached while in the air, and then measure the distance between that and the point of contact when landing. This would also remove the need to constantly update the fallDistance field. However, this would involve a BC break and will therefore have to wait until PM4.
This reverts commit b172c93e45.
I made a significant mistake with this change: the scaling factor of
batch-by-chunk is O(nSendBytes), while the scaling factor of sending
directly to players is O(nSendBytes * nActivePlayers). It seems like the
real problem is that this system isn't getting enough usage.
While it does reduce compression efficiency in some cases, it falls back
to letting the sessions do individual compression when the amount of
data is less than 256 bytes anyway (compression-threshold in
pocketmine.yml).
My motivation for scrapping this system was to reduce the broadcast
system's complexity to make it easier to thread the living shit out of
compression, but it seems like this change was a step in the wrong
direction for performance.
A few steps can be taken to improve the usefulness of this system (and
also improve output bandwidth):
- Make general entity updates use this system. Movement and velocity
already kinda used this system, but crucially, players did not,
because we couldn't prevent the player from receiving its own movement
updates if we did that, which caused all kinds of problems.
- Therefore, we need to reintroduce static "self" entity IDs, like we
had in the shoghi days when entity ID 0 referred to the "self"
player.
- However, since entity ID 0 has a variety of interesting bugs since
it usually refers to "no entity" in MCPE, it would be better to use
1 (or 2, like MiNET does).
- The fixed ID used should be close to zero to maximize varint
encoding efficiency.
- We assumed that changes to player's position and velocity would be
ignored by the client. This assumption depends on the client and
could be broken at any time, so it's best not to rely on it.
- Make block updates use this system (when chunk updates are not sent).
Currently, block updates use a separate mechanism which creates a
second batch for every active chunk, which wastes CPU, and decreases
bandwidth efficiency on multiple fronts (reduced compression
efficiency, more cross-thread interactions, more bytes wasted on
RakNet packet headers).
it's not clear what this was actually supposed to represent, but it actually reports VmSize, which is already reported by "Total virtual memory". This line confuses users and is misleading.
player knockback silently depended on the chunk packet broadcast system sending the player's motion back to itself, which broadcasting to hasSpawned will not do.
On larger packets, this worsens compression ratio by 1-2%, but reduces CPU load due to compression by 15-20%. Higher levels than 6 are far more expensive for diminishing returns.
Level 5 produces a further 25-30% CPU reduction, but increases bandwidth usage by 20-25%, so 6 is the sweet spot.
Grouping packets to batch by chunk instead of by player reduces bandwidth efficiency, because the number of active chunks is almost always larger than the number of active players.
With the old mechanism, a batch of packets for each active chunk (which could be dozens, or hundreds... or thousands) would be created once, and then sent to many players. This makes the compression load factor O(nActiveChunks). Broadcasting directly is simpler and changes the load factor to O(nActivePlayers), which usually means a smaller number of larger batches are created, achieving better compression ratios for approximately the same cost (the same amount of data is being compressed, just in a different way).
This change was made after exploring turning this into a permission. It occurred to me that this feature is entirely superfluous because it's non-vanilla, can be done by plugins, and is usually considered as a bug. In addition, disabling this behaviour required third party code just for this one thing because it was not able to be managed by a permissions plugin.
Instead, it's better to produce a plugin which implements this behaviour if it's desired, by making use of SignChangeEvent and PlayerChatEvent/PlayerCommandPreprocessEvent.
close#3856, close#2288
Not allowing this makes stuff like anvil damage, colour, wood type, live/dead bit, wet/dry etc all too much hassle to deal with.
Naturally I want to get rid of this shit altogether, but first it's necessary to construct a new system that we can shift into before all this bullshit can be addressed fully, so for now we have to work within the bounds of the old system.
This change will permit dynamic colours for concrete/concrete powder etc, dynamic wood types where the wood type isn't embedded in the legacy ID, and so forth. Allowing full flexibility requires either more old system hacks or completing the migration to a new system which doesn't have these limitations. I prefer to do the latter, but this change will make it somewhat easier to do.
The motivation for this is to prevent passing a dynamic argument to cancellation, which in almost all cases is a bug in user code. This same mistake also appears in a few places in the PM core (as seen in this commit), but in those cases the mistakes were mostly harmless since they were taking place before the event was actually called.
closes#3836
this produces a major performance improvement for large render distances, and reduces the impact of lighting calculation to zero on servers which have random blockupdates turned off.
this fixes TNT spawning multiple entities when lit by flaming arrows.
The problem here is a bit more complex (entities aren't immediately notified when local block updates happen, so they cache stuff that becomes unusable). The simplest option would be to just lose the cache, but that would have some impacts on performance.
Barring a rethink of the block updating mechanism, this solution seems usable for now.
again, this should never happen, because chunk unloading cleans this stuff out. But if it did happen, loading chunks is not the way to take care of it.
this should never happen, but it could have happened if there was a bug in the code for some reason.
Readers note: I know this looks lik I'm undoing the changes I just did, but what really happened is a name change.
Various bugs existed for a while with stuff using chunk managers instead of worlds when interacting with terrain due to a behavioural inconsistency between World::getChunk() (return from cache or load from disk), and SimpleChunkManager::getChunk() (return from cache only). This change brings the two in line.
World::getOrLoadChunk() has been added as a replacement, which has the same behaviour as the old getChunk() and also makes it more obvious that there is an issue with code using it during refactoring.
the expectation is that eventually this will receive arbitrary internal runtime IDs instead of static id/meta, and RuntimeBlockMapping doesn't really care about this crap anyway.
PHPStan has no idea what is going on in this code because unpack() returns mixed[].
Possibly it might be a good idea to implement a dynamic return type extension for this.
this solves multiple architectural issues:
- improves reusability by avoiding having old state info stick around to fuck stuff up
- prevents access to propagation state from outside of propagation
this also reduces the latent memory usage of light-updates after they have been used.
TODO: we could probably change LightPropagationContext to LightPropagator and move all the propagation-specific code into it if we can solve the subchunk-iterator and effective light problems.
this new form allows skipping some useless checks during sky light calculation and also allows getting rid of the last hard dependency on core Block classes.
We're getting real close to native light now.
I accidentally added this during a separation of my local changes, but it's useful anyway, so we should use it.
This removes BlockLightUpdate's implicit dependency on Block, which is a
step towards native light.
it's useful to have an immutable stub around for the sake of feeding back dummy read values, but for write values it has to barf instead of being quiet.
There's still some issues with LightArray which I don't currently have a solution for, but I'm thinking about separating light storage from chunks anyway.
recalculateHeightMapColumn is stateless, so it can't make any assumptions about which subchunks to check for blocks. However, in most the average case (6 allocated subchunks), this causes 2500+ useless SubChunk->getHighestBlockAt() calls (10 per column). Since we're calculating in bulk, we can figure out which subchunks are empty one time and ignore them for all 256 columns.
In the average case, this produced a 50-60% performance improvement for heightmap calculation (~1.1 ms -> 0.5 ms).
In extreme cases where the height is extremely varied, this produces no observable performance benefit, but for most cases with flattish terrain, it's an improvement.
It can likely be further improved, but further performance improvements are outside the scope of this commit and will likely result in more complexity increases.
typically this is a state that only lasts for a tick or so, but it's a race condition that is regardless very commonly encountered.
If you were very unlucky, you might have noticed grass randomly dying when you were spawning or flying around, even though it was in full sky light.
non-class constants aren't stored during preloading phase and for some reason they aren't pre-resolved in opcode arrays. However, they are resolved by value when referenced by class constants, and class constants stick, so we can use those instead.
opcache preloading doesn't store non-class constants, but it does store class constants. Class constants that reference non-class constants are pre-resolved into values before storing in opcache SHM, so class constants are OK to use, but non-class constants will come back as undefined.
this was degraded whenever it was I decided to make chunks always be allocated. This commit uses a fast path for light filling in subchunks which are completely clear of the heightmap, which returns the performance back to its old fast levels.
running composer update on 7.4 will generate a lock file using the newest dependencies which work for the current PHP version, which usually isn't desirable for a project like this where developers might be using newer PHP versions than users.
running composer update on 7.4 will generate a lock file using the newest dependencies which work for the current PHP version, which usually isn't desirable for a project like this where developers might be using newer PHP versions than users.
This commit fixes the 5+ years-old bug with the movement anti-cheat that everyone has complained about: sprinting on stairs causes rubberbanding.
This commit addresses this problem at long last, along with a handful of precursor commits that were necessary to fix this problem:
- dac76f0e0f
- 89fe8f7f10
- 2d77b1e364
Additionally, these changes now allow the anti-cheat to be accurate to at least 0.001 of a block, perhaps even better. I didn't commit a change to the threshold here, but it was instrumental to pinning down the exact nature of these bugs.
This closes#1475, at long last.
this fixes bugs where the entity would jump in the air when walking on blocks like carpet. It also fixes a lot of the issues with stepping in the anti-cheat, allowing to reduce the error tolerance on movement processing.
this was causing the movement anti-cheat to shit itself after the first movement because it used setPosition() on the player if the position wasn't exactly perfect (which obviously it never is perfect, because of fp rounding errors).
this allows it to be imported by other repos using the same config (for example plugins needing PHPStan analysis) without them needing to copy paste big blocks of shit every time something little changes.
since the removal of EntityFactory::create() this isn't needed anymore, since these creation functions are only used for creating entities loaded from disk.
this bug became painfully obvious when testing bamboo. Detonating TNT near tall bamboo canes would result in bamboo canes not deleting themselves in some circumstances, because the non-destroyed parts of the cane would be updated before their supporting block was deleted, and subsequently would not be re-updated afterwards.
I think this bug should also reproduce with cacti, but I have not tested.
this version doesn't change any packets as far as I know, but it does change some packet content (most notably, some blockstates changed, which are troublesome when not in sync).
this allows generating a docblock / code for a registry without the class needing to exist or be populated yet, which makes code generation significantly less cumbersome.
fixes#3655, fixes#3241
instead of guessing where the end of the transaction is, we attempt validation after every piece of the transaction, with the assumption being that a crafting transaction will not validate until it's complete.
this will be needed for more than just this little check once item NBT gets cleaned out properly, since we'll need to compare object equality by network layer stuff instead of internals (where different network objects might deserialize to the same internal items).
if the order of the constructor parameters were changed, it would cause these statements to be reordered, causing packet fields to be decoded in the wrong order.
ChunkListeners are less dangerous, and also make more sense considering the usages.
Ideally we want to not have to care if a listener is a Player at all, but that's still some work away yet.
* Removed `setCancelled` from `Cancellable`
Before anyone screams, THIS CHANGE WILL NOT AFFECT MOST PLUGINS
(although it allows future changes to break some).
This commit rewrites the documentation of `Cancellable`,
clarifying the concept of "cancelled" from the perspective of the event
framework.
This commit also removes the `setCancelled` method from `Cancellable`.
This does not affect plugins using the (originally standard)
`setCancelled` method on events directly, since the implementation on
classes was not removed. On the other hand, it no longer requires
`Cancellable` events to implement this method, allowing flexibility on
cancelation conditions, e.g. subclasses may require additional
parameters for cancellation without needing to use hacks to check that
the user cancelled the event in the correct way.
in pretty much every case, these usages really wanted to read the tag's contents anyway, which can be combined with a getTag() and instanceof call for more concise and static analysis friendly code.
In the few cases where the tag contents wasn't needed, it still wanted to check the type, which, again, can be done in a more static analysis friendly way by just using getTag() and instanceof.
apparently plugins like to pass around positions which have null worlds, which aside from being quite stupid, also breaks a lot of stuff and makes it look like PM is to blame when it's just trying to make everything work the way it's supposed to ...
this fixes#3200.
This causes permissions to be registered before plugin load, which changes some behaviour, but after discussions on #internals-dev we couldn't see any reason to keep the behaviour the way it was, and several reasons to change it to be something like this.
This fixes undefined behaviour when scheduling the same task twice. This is usually accidental and almost never desirable.
Note that this still allows a task to be scheduled again after it has
been cancelled; it only disallows scheduling a task multiple times
concurrently.
This commit will probably break MyPlot and other plugins that have
self-scheduling tasks, but as far as I can tell those use-cases should
be replaced with self-cancelling repeating tasks anyway.
this will still take effect for preexisting data because the server will still see previously set spawns as custom, but for new players, their spawns will follow the world spawn unless they sleep in a bed.
I wonder if there's a way to generalise item consuming beyond just eating/drinking. Stuff like lava bucket in a furnace needs the same kind of "leftover" logic.
there's a few changes that can be made to avoid this problem, the
primary one being to separate this API from NetworkSession and abstract
it away... but this is a reasonable, although not great, solution.
this fixes crashes and various bugs with death logic executing during the creation of entities, as well as an age-old Player crash after quitting the server when dying.
this commit removes the ability to replace centrally registered entity classes in favour of using constructors directly.
In future commits I may introduce a dedicated factory interface which allows an _actual_ factory pattern (e.g. factory->createArrow(world, pos, shooter, isCritical) with proper static analysability) but for now it's peripheral to my intended objective.
The purpose of this change is to facilitate untangling of NBT from entity constructors so that they can be properly created without using NBT at all, and instead use nice APIs.
Spawn eggs now support arbitrary entity creation functions like EntityFactory does, allowing much more flexibility in what can be passed to an entity's constructor (e.g. a Plugin reference can be injected by use()ing it in a closure or via traditional DI.
this allows doing stuff like injecting plugin references to entity constructors for now. I want to make this more flexible still, but I've done about as much as I feel like doing today and don't want this disappearing into a stash to never be seen again.
this may be different from the IDs exposed on the API and shouldn't be used for anything outside the protocol.
TODO: we need to review the dynamicness of item numeric IDs and find out if it's possible for them to change based on StartGamePacket content. If they can, we might need to change this.
I'd like to have this directly provided to Furnace, but I don't know how to short of making into a singleton. Since I want to have per-furnace recipe managers (e.g. for stuff like blast furnace vs regular furnace etc), a singleton isn't really an option.
this reduces the temptation to use it in high-level code, as well as making syncNetworkData() more useful (now it can export to many data collections, which means we can start to think about having a property cache per network session, which is more flexible)
Now, blocks do not respond to silk touch unless specifically opted into. Since this always involves custom drops in one way or another, it's easy enough to figure out which blocks need to be marked for silk touch - anything that overrides getDrops, getDropsForCompatibleTool or getSilkTouchDrops is a block which _might_ need to be flagged. Using these criteria to reduce the number of blocks needing to be checked, I was able to manually invert the behaviour as needed.
This fixes reoccurring bugs with blocks erroneously dropping themselves whenever new blocks are added and someone forgot to set that flag, granting players access to internal blocks with strange behaviour.
this would have allowed clients to send SetLocalPlayerAsInitializedPacket at any time during the spawn sequence, which would have caused undefined behaviour around spawning logic.
this removes a whole bunch of crap from its API that shouldn't have been exposed. In the future we should look at splitting this into reader/writer halves, but for now this is a step in the right direction.
This parameter is not used for the vast majority of task use cases and just serves as extra useless boilerplate code, especially for closure-based tasks.
This use case can be replaced using Server->getTick() in the cases where it matters.
this fixes a few crashes that could appear from invalid plugin_list.yml setups, which was the reason #3228 was opened to begin with. Respect also has nicer error messages, as long as you don't use the static API :)
previously this might just return false and blow up in your face.
I considered fixing this on stable too, but it's less useful there because so much stuff on stable just explodes at the first wrong thing anyway.
just treat them as unknown items instead
this might break some use cases, but at least this way they won't crash the server when read from disk and they won't get lost either.
this had been planned for a long time already, just never finished.
It's not fully done, because there needs to be synchronization of block-break handlers between different players attempting to break the same block, but this should resolve a lot of the bugs that previously existed, while also opening the doors to making the logic more flexible.
this makes it much easier to observe and debug stuff that depends on it, such as grass, crop and tree growth, since they'll happen much faster.
A future improvement would be to have the update function use a non-global random so that the output can be reproduced using a given seed.
pthreads will screw around with it and make it do things it's not supposed to, which is the exact reason why we have thread-local storage to begin with.
this isn't strictly necessary because it could be done by removeListeners(...getListeners()), but I think developers will appreciate not needing so much boilerplate code.
the compressor used by RakLibInterface when opening a session is still
hardcoded, but that's because we have no way to select the correct
compressor at that point in the login sequence, since we aren't
propagating the protocol information up from RakLib right now.
this prepares for a fully dynamic block mapper, as well as allowing a small performance improvement to chunk encoding by eliding the constant lazy-init checks.
at this point it's really not much more than just a thread-safe way to transmit parameters from main to thread. Maybe we can ditch it in favour of a generic closure-based thread implementation.
this optimization relies on the fact that palette entries are always unsigned, and positive zigzag varints are just the same as their non-zigzag counterparts, except shifted left by 1 bit. This eliminates some function call overhead, making the encoding slightly less agonizingly slow.
this is not complete yet, but the final change (having the binarystream actually come from outside) is a little more disruptive, and some extra changes need to be made. This will grant some sanity in the meantime without breaking too much stuff.
this eliminates feedback loops during client-initiated slot changes, and also makes it possible to have a SlotChangeAction anonymous from its initiator.
the useHeldItem() sets the using-item flag back to true immediately after consumeHeldItem() sets it to false, which caused this bug.
stable has the same problem, but the effects don't show due to a well timed MobEquipmentPacket (a happy accident).
TextContainer provided zero real value as a base of TranslationContainer, given that it required its own logic to be handled wherever accepted. As such, it's no better than a simple string.
Removing it also allows fixing an ambiguity when embedding translations inside other translations, allowing it to be made immutable.
technically there wasn't anything wrong with this code, but it caused the type inference to report incompatibility, and I can't be bothered to report a PHPStan bug.
often we throw out actions that have no value, which can lead to an empty transaction and re-syncing the inventory. This happens every time we interact with the creative inventory in 1.13+, which causes items to appear to vanish when taking them from the creative menu.
The correct fix for this is to resend only the slots affected by SlotChangeActions, but this fix will suffice for now without rewriting everything.
comparing enums with equality operators is unreliable because there is no guarantee that the enum objects won't be somehow duplicated, through serialization, cloning or ext-parallel dumb object copying. This means that two equal enum objects may not be thw same object.
we don't expect plugin devs to be using this any more, and it doesn't make sense to throw on data deserialize. This throw was unchecked and a potential server crash might have occurred in Living on data load.
these are too specialized to be of any use to plugin developers, and they are also misleading - plugin devs often think this refers to the highest block Y coordinate, but it doesn't.
copy-on-write and zero-layer SubChunk objects are much easier to manage and have less cognitive overhead.
obviously, the goal is to get rid of EmptySubChunk completely, but right now it does still serve a purpose (filling in dummy values for reading out-of-bounds on chunks), and that's a problem that takes a little more work to fix.
this is more efficient (less data copied for ITC), fixes#2873, and also fixes terrain changes during task run getting overwritten.
This still leaves the problem that the light information provided may be out of date by the time the task completes, but this is nonetheless a step forward.
This was intended to try and mitigate player movement clipping through blocks triggering anti cheat. Now that the anti cheat is gone, this code is no longer needed.
this was intended to make available things like the deviceOS, input method etc without placing an API requirement for custom implementations to provide such information.
these usages make no sense in the contexts they are used in, because their uses require another BB to be created anyway. It makes more sense to simply destroy the old one instead of having it mutable.
this allows multiple problems to be solved:
1) Cycle between tile and inventory is now removed.
2) BlockInventory now provides a consistent API for plugins to get the block holding an inventory.
this bug was introduced by 211836274f, which did not take into consideration that the dirty flag is cleared after the first time the chunk is saved, meaning that later entity and tile changes wouldn't be saved.
I considered this fix more elegant than reverting the bug commit.
- Only sync the metadata set when needed for sending
- Don't use metadata set for storing data, add properties instead
- Use objects inside metadata sets instead of arrays
it doesn't make sense to set the level of an existing enchantment instance because under the old API it would have no effect anyway (if it was returned from an itemstack) or you had access to the constructor (if applying a new enchantment). Allowing this to be mutable creates needless complexity and performance headaches.
putting this stuff on the API creates a nightmare because DS structures are both mutable and by-reference, so they have to be manually copied everywhere.
this is a more tame version of my initial attempt to firehose item NBT. It marginalizes the use of item NBT to the places where it's needed on interfaces, leaving the internals clean to operate on whatever they like.
some clients send things without the /, f.e. websocket stuff, and we aren't ready to handle that properly yet. The result is that the command gets dumped directly into the chat instead of being unhandled.
these were added in 2017 with the intent of async'ifying light updates. However, light updates now use an optimized code path which bypasses these functions completely, rendering them useless.
these were slated for removal some time ago, but it never happened because they were used in the API. This is no longer the case on 4.0, so these classes are now entirely useless.
the intentions of this are good, but the usability is terrible and it's not fit for purpose. Since there are a total of zero plugins on Poggit which use this garbage, it makes more sense to eliminate the technical debt. See #2766 for discussion about replacing this.
the reasoning for this is that the world version number should have accounted for a chunk format change. If it didn't, then we assume any chunk with a wrong version number is corrupted, since the handling of unknown formats is the same as that of corrupted chunks.
- This fixes InventoryOpenEvent and InventoryCloseEvent being fired for persistent windows. Close#2950
- The ability to specify a custom network ID to assign the inventory to in addWindow() has been removed.
- The ability to assign a non-removable window in addWindow() has been removed.
- The ability to remove non-removable windows in removeWindow() and removeAllWindows() has been removed. This was previously needed for internal purposes.
since we already have a partial implementation of brewing stand, we should also have the corresponding tile so that PM doesn't create any more busted blocks.
these properties are continuously updating when the furnace is active, but they never trigger cache destruction, which means this is sending outdated garbage over the network, which is entirely unnecessary anyway.
this was an old hack to prevent debug spam being emitted when we halted decoding of logins over breaking protocol changes. Since then, we've gone back to trying to decode the packet regardless, so this property is useless.
There are a few motivations here:
1) Less boilerplate code (this can be written inline)
2) It's possible to provide multiple constructors for different packet variations to reduce the chance of errors.
3) It makes things catch fire on updates in ways that static analysers can understand.
this doesn't come with a full impl because that requires some further changes like adding materials, which is out of the scope of this commit. This is here to prevent additional data loss in imported worlds.
Non-closure callables have strange context-dependent behaviour and are slower to call than a closure. It's possible to use Closure::fromCallable() in the origin scope, which guarantees that the callable will remain callable no matter where it's used.
Warning for plugin developers: This is a silent BC break. It won't raise any errors.
This alters the default behaviour of event handlers to **not** receive cancelled events by default.
It is now required to opt into receiving cancelled events by using the @handleCancelled directive (or the handleCancelled parameter where it's appropriate).
The ambiguous @ignoreCancelled directive is now ignored.
Ramifications:
- The majority of handlers with `if($event->isCancelled()) return;` no longer need such checks.
- Handlers with `@ignoreCancelled true` or `@ignoreCancelled` annotations can have them removed.
- Handlers which want to receive cancelled events need to use `@handleCancelled`.
It's not guaranteed that objects provided are the same as those in the enum registry, so they can't be directly compared.
Implementing comparison with === would require some kind of __equals() implementation or an extension to hook into such functionality.
given that inventory listeners are no longer allowed to fiddle with the outcome of changing contents, it's now possible to allow having multiple listeners receiving events.
It's likely that this will be used for network inventory sync in the near future.
there is nothing that these events do that can't be fulfilled by transactions. They complicate the internal implementation and produce unexpected behaviour for plugins when cancelled.
TL;DR: Use transactions. That's what they are there for.
the "simple" name comes from the early days of this refactor before I started splitting everything up into their own units. This handler is now in good enough condition to have a proper name.
this causes bugs when a packet is modified during events and then re-sent to a player. Since we can't control this, we can't allow this kind of buffer reuse.
The only notable case where this will cause loss of performance is when broadcasting a series of packet(s) which accumulate to less than 256 bytes, which is reasonably cheap to encode anyway.
In addition, removing this caching is one roadblock to moving this serialization to native code, which will make it vastly faster.
I'm wondering if there is even a point to Flowable at this point. Half of the blocks inheriting from it do not break instantly, or have some other modification to tool requirements.
these functions belong in the network session, and they are currently just proxies for them. In the future we might have players who don't have IPs at all depending on how they connected (for example Specter) so this stuff shouldn't be in here.
it's better to encapsulate all this logic in one place so that third party developers can more easily understand this, and also to reduce the amount of crap we have in Player.
the checks removed here should never be hit under normal circumstances. If they were hit, they'd just conceal bugs which would cause a crash to happen later anyway.
there's nothing that can be done with this event that can't be done with EntityTeleportEvent. Having this extra event needlessly increases system complexity.
This has been a pain point for a long time due to the misleading nature of the name "level". It's also confusing when trying to do things like getting the XP level of the player or such, and also does not translate well to other languages.
This transition was already executed on the UI some time ago (language strings) and now it's time for the same change to occur on the API.
This will burn a lot of plugins, but they'll acclimatize. Despite the scary size of this PR, there isn't actually so many changes to make. Most of this came from renaming `Position->getLevel()` to `Position->getWorld()`, or cosmetic changes like changing variable names or doc comments.
this is necessary because some handlers have circular references to the session, which causes GC lag collecting them. This change allows them to be collected immediately without nuking internal state.
These methods are commonly mixed up when we talk about thread-local storage. What these things actually do is store persistent data on the worker thread.
this is more in line with expected behaviour, since this might be used to process arbitrary user input. Only calling an undefined magic static method should throw an Error.
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.
this is not remotely a complete implementation, it's just here to make PM aware of these states so that world conversion can be handled correctly. A full implementation will come later.
Any blocks added in this fashion should be marked with a //TODO so future maintainers can find which blocks need work.
For many years, this has been the cause of many users (particularly plugin devs) confusion. The reality is that /reload has little to no practical value. It does not reload plugin source code (contrary to popular belief).
1. The current Dockerfile is not directly related to the project, but just our very complex highly-coupled full-of-hacks build/release/deploy system.
2. We are no longer using Docker Hub Builder. An internal Dockerfile will be used on our Jenkins server instead, using the correct upstream phar build to prevent race conditions.
this can't be reached because the only place it's called is from Level->actuallyDoTick(), where it won't appear until long after the player is logged in.
The reason this uses a trait is because `self` refers to the including class in a trait, which offers a small amount of automatic type safety.
If we had templates or generics, this would be a generic class instead.
This opts _not_ to expose item "age" a la #2753 because "age" is a misleading term for it. In addition, further inspection of the problem led me to realize that exposing control of that AND despawn timeout was more complicated than simply having a despawn delay timer exactly like the pickup delay one. Everyone knows a countdown timer stops at 0, so this way we don't need any method to control the limit.
Closes#2667Closes#2753
past me was full of shit, because blockReplace is the same as blockClicked when we click a single slab top/bottom to make a double slab, and the logic is identical to the below block with that in mind.
this supports placement, toggling compare/subtract mode, simple stuff. No redstone functionality yet.
This is needed for blockstate mapping in blockfactory.
some of these (notably the on* methods) are internal and shouldn't be exposed via interface (same crap as Plugin->onEnable() onDisable() etc) and the rest of the stuff is entirely unused.
This story dates back to the days when getVariantBitmask() was introduced. The purpose of this function was to allow the variant info to be extracted from the metadata, for use with item drops. This was later changed to state bitmask for reasons I don't clearly recall.
In the great 4.0 refactor, we now store variant magic numbers separately, so we don't need any generic bitmask to split up variant and state information anymore. Variant is now only ever serialized and never deserialized. The same thing goes for blockIDs. States are read from the world by matching the full stateID against a table of prefilled known blocks, so the variant doesn't need to be deserialized - only the state does, and the state metadata readers already do bit fuckery by themselves and don't need this mask - notice how little actual changes were required to get rid of this?
This test is intended to enforce that the BlockFactory always has the same blocks in it from one commit to the next. Since there are a lot of changes going on right now around this, it's important that this is checked because bugs can go under the radar when large changes are happening.
The consistency check will need to be regenerated whenever a new block is registered, new states are found or when things are removed.
it's unclear what the purpose of this flag is. It appears to always be set on placement and is never changed at any other time. The result is that the hitbox becomes larger when it is set.
this is a bad fix, but it doesn't matter a whole lot. The problem stems from furnace not having a valid 0 variant, so things go haywire when the default mapped 0 variant is registered to LIT_FURNACE because the default state is of course unlit.
This is similar in nature to 646fea5a4e.
On a side note: Migrating this way is a pain in the ass due to lack of types. What the heck is int supposed to mean?!?!?!?! At least if we wanted to go _back_ to magic numbers, it would be easy to locate everything with an Enchantment typehint...
This introduces static getters for every currently-known effect type. At some point in the near future, the magic number constants (which are really network IDs, by the way) will disappear.
Migrating:
- If you used constants (like any sensible person would): for the most part it's just a case of adding a () anywhere you used an Effect constant.
- If you hardcoded magic numbers: ... well, have fun fixing your code, and I reserve the right to say "I told you so" :)
This achieves multiple goals:
1) creating an EffectInstance for application is much less verbose (see diff for examples, especially the Potion class)
2) plugin devs cannot use magic numbers to apply effects anymore and are forced to use type-safe objects. :)
This is a warning shot for plugin devs who use magic numbers. More changes like this are coming in the not-too-distant future.
populateChunk() _sometimes_ does this, but not if the chunk is locked. This means that the empty chunk needed to prevent the shit hitting the fan isn't created when chunks are locked. This change resolves the problem because registerChunkLoader() calls loadChunk() with the create parameter as true when autoload is used. This is a shitty fix but it's the simplest one we have right now, and it works well.
getOfflinePlayerData() will now return NULL if there is no stored data for a given player. The responsibility of checking the spawn point is now delegated to the Player, after it registers a chunk loader on its spawn chunk.
Blocks were being overwritten in the writebatch which hadn't yet been set, so reading them from the world yielded air blocks instead of trunk, allowing the generation to overwrite blocks which should have been logs.
This prevents plugins sending wrong packets at the compiler level (or would, if we had a compiler). It's more robust than a getter for client/server and throwing an exception since a static analysis tool can detect faults created by sending wrong packets from the server. This is also used to deny service to dodgy clients which send wrong packets to the server to attack it.
this is in preparation for clientbound/serverbound packet separation. I did this already on another branch, but the changeset was dependent on a massive refactor to split apart packets and binarystream which i'm still not fully happy with.
This is a bolt-on feature that can't be disabled and causes serious grief for Unix server users, because it prevents ctrl+c aborting the server the normal way.
Instead, we prefer introducing a plugin to implement this functionality, so that users can opt-in or opt-out.
The only cyclic references here are both destroyed during normal collection directly (net interface removes from sessions array, player destroys its session reference), so there's no need to destroy them again here. This just causes a giant swathe of potential crashes for no real benefit.
close#2669
this has been a bug for a long long time. I think the reason it was never addressed is because of the performance impact associated with it. However, that performance impact is now gone thanks to light update batching.
this allows deduplicating block updates when lots of adjacent blocks are set on a tick, which has beneficial effects on performance. It also fixes#2659.
Future scope:
- Use this mechanism to deal with explosions properly.
- Don't execute block updates for air blocks.
future enhancements:
- make gamemode an object containing information about abilities that players have in this gamemode (gamemodes are just predefined ability sets)
- get the magic numbers out of the API
This contains all of the static stuff that was previously embedded in the Entity static root. This solves a bunch of problems like circular dependencies between parent and child classes, encapsulating logic and reducing the size of the enormous Entity.php.
This is a similar refactor to the one I recently did for tiles.
- Entity::createEntity() is removed. In its place are Entity::create() (runtime creation, use where you'd use a constructor, accepts a ::class parameter, throws exceptions on unknown entities) and Entity::createFromData() (internal, used to restore entities from chunks, swallows unknown entities and returns null).
- Entity::registerEntity() is renamed to Entity::register().
- Added Entity::override() to allow overriding factory classes without touching save IDs. This allows more cleanly extending & overriding entities. This method only allows overriding registered Entity classes with children of that class, which makes code using the factory much more sane and allows to provide safety guarantees which make the code less nasty.
- Entity::getKnownEntityTypes() is renamed to Entity::getKnownTypes().
- ProjectileItem::getProjectileEntityType() now returns a ::class constant instead of a stringy ID.
- Cleaned up a bunch of nasty code, particularly in Bow.
@shoghicp, y u do dis... I almost created a sub-packet architecture to deal with this shit :(
This mess really ought to be split into multiple packets. Perhaps the PacketPool can be extended to do that in the future.
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.
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.
garbage collection does need to be implemented, but I was looking at this code and found so many fucking bugs I decided it wasn't worth the effort of fixing.
This filters out over 200 invalid states which were previously considered just fine, including zero-width cakes, buttons with broken facing values, furnace/chest with crazy values, and more.
This breaks down the handling of tile creation even further.
- Introduced a static Tile::override() method to allow overriding the construction class for a specific type of chest. This applies to classes as opposed to save IDs, so you can override Chest::class with MyCustomChest::class and it will take effect for any Chest save ID.
- Removed MCPE stringy save ID constants from public Tile interface. These are now only used for creating saved tiles from a stored chunk, and saving them.
- Renamed Tile::registerTile() to register()
- Tile::create() and Tile::createFromItem() now accept a class parameter instead of a stringy save ID.
- Tile::create() and Tile::createFromItem() were changed to throw \InvalidArgumentException on unknown/unregistered tile types. They also now never return null, but always (except in exception cases) return an object which is an instanceof the base class specified.
This allows plugins to more easily control the behaviour of server-full, whitelisting and banning. A message can be assigned for each, with a plugin custom reason taking the final priority if set.
This system solves several edge case problems in the Bukkit version by allowing kick reasons to be combined, so that removing one kick reason will roll back the final reason to the next highest, instead of just allowing the player through completely.
Only one message will be shown at point of disconnection, for consistency with the old behaviour.
The message priority is as follows (for all cases, only if set):
- Plugin reason
- Server full
- Whitelist enabled
- Player is banned
This also brings us one step closer to separating Player and NetworkSession.
Previously the only way to deal with this was to cancel the PlayerKickEvent generated by lack of authentication. Now, plugins can decide whether auth should be required for a specific player. The default is whatever xbox-auth is set to in server.properties.
cc @Johnmacrocraft
since this is an internal method, it doesn't make sense to force a single parameter that requires potentially constructing a separate object just for the parameters, so we pass primitives instead, which are also easier to typehint against.
calculating dynamic states in some cases requires getting properties from neighbouring blocks, but getting these blocks also causes their dynamic states to be calculated, leading to a bouncing recursion.
This change allows retrieving blocks without calculating dynamic state information, if the call was generated by calculating dynamic state information.
Since these blocks are incomplete, they should not be cached and are only used to allow another adjacent block to complete its state. It is therefore not possible for a block's dynamic states to depend on another block's dynamic states.
This recursion bug was observable by running /gc and walking into a door, which would cause the server to freeze and crash.
This was the cause of many inconsistency and broken world bugs. In the future (once we switch to paletted chunks) this won't be possible anyway. For now, some temporary API is provided to allow modifying chunkdata directly, but it is required that **both** must be provided.
This cleans up some cargo-cult code poorly copied from Bukkit, which has negative performance effects and also makes internal event handling more complex than necessary.
## API changes
- Removed `EventExecutor` and `MethodEventExecutor`.
- A listener is no longer required for an event handler to be registered. Closure objects can now be used directly provided that they meet the conditions for registration.
- `PluginManager->registerEvent()` signature has changed: the `Listener` and `EventExecutor` parameters have been removed and a `\Closure $handler` has been added in its place.
- `RegisteredListener` now requires a `Closure` parameter instead of `Listener, EventExecutor`.
## Behavioural changes
These changes reduce the execution complexity involved with calling an event handler. Since event calls can happen in hot paths, this may have visible positive effects on performance.
Initial testing reveals a performance improvement of ~15% per event handler call compared to the old method.
This removes the need for custom Plugin implementations to implement onCommand().
In the future it's planned to remove plugin.yml commands completely and have them registered similarly to how events are handled.
This greatly improves GC performance by being more intelligent about how it collects garbage tasks. It knows that if X task in the queue is not finished, none of the tasks behind it can be finished either, so there's no point checking them.
This also presents the opportunity to cleanup a lot of async pool internals, so I've taken it and torched a lot of garbage.
This will be needed to deal with things like chest/furnace which don't use 0 as a valid state (these both use facing horizontal for rotation, and vertical is invalid, so 0 would mean downwards facing which is invalid.
The client likes to fall involuntarily as soon as PLAYER_SPAWN PlayStatus is sent, which causes debug spam on the PM side and then movement reversions if falling far enough. This now prevents the client moving until the server knows the client has spawned.
These methods:
a) add concrete dependencies
b) are pointless (event->getEntity() instanceof Creature, anyone? an IDE can better understand this as well...)
c) encourage bad code (they don't enforce type contracts the same way an instanceof check does - oh, and why not let's add an is*() for every new mob that gets added ever?
This reverts commit 3bb450244f.
PhpStorm you lying piece of shit... you only showed me the usages in Level!
This change should be revised and redone later.
chunkloader ID is completely unnecessary extra complication. spl_object_hash() would be fine for this as well, but a number is better. Since it's unique for the object lifetime (and the Level keeps a ref to loaders) this system should work just fine.
This is intended to break API in order to jerk the rug out from underneath plugin developers who have been misusing this without noticing the side effects.
This is now self-maintaining and doesn't rely on the async pool to wipe its ass on task completion. Instead, the garbage collector will cause thread-local data to be automatically released when the async task is garbage-collected on the main thread.
It was still possible to produce undefined behaviour by creating a db folder in a region-based world, or adding regions to a leveldb world. This now solves the problem completely by refusing to load the world if multiple formats match the world.
Seed is immutable information about the world, like its generator type, generator options, name, etc. We don't allow changing any of those things, so why the fuck would we allow changing the seed? This makes no sense at all.
I'm removing this because a) its existence makes no sense, and b) it will not produce the behaviour expected from such a function (what even is the expected behaviour???)
It checks for the existence of (and creates) the world directory if it doesn't exist. But what sense does this make when the world obviously doesn't exist in this case and must be generated first?
This is problematic because child level providers can forget to override the provider name of their parents, and then override them by error. Instead, they should be used in a mapping fashion to make sure they are unique and not inherited.
Also, the old method did not permit registering multiple aliases for the same provider. This now makes that possible.
In the future, McRegion and PMAnvil will become deprecated legacy formats which we won't support for writing anymore. However, this brings complications because Anvil (which would not be deprecated) would be sandwiched between its deprecated base (McRegion) and its deprecated child (PMAnvil), complicating the implementation (particularly for PMAnvil).
This abstracts away the generic Region-based world functionality into a separate class, making McRegion, Anvil and PMAnvil all inherit from it directly. Since only the chunk formats are different, they are more accurately siblings rather than parent-child (although Anvil and PMAnvil are cousins, ish).
The cause of this was the flow decay of falling water changing, but the flow decay is ignored for falling water. This caused the block to be repeatedly set to itself, triggering local block updates, causing the disease to spread in large falling water bodies and cause immense amounts of lag.
this parameter was previously used to send blocks with a different set of flags, immediately, to players. However, the flags have been demonstrated useless and the direct sending is pointless now since packets are buffered now per session, so we might as well take advantage of the batched block update sending.
These flags are not intended for network use, instead they are supposed to be used internally by the game. For network, we only need to care about the 0x02 flag (send to players) because that's necessary for the client to render the block.
This is only implemented in 1 place where the collision box should just be zero anyway, so there's no point this existing.
There's a lot of other blocks which should have bounding boxes without collision boxes as well, but that's outside the scope of this commit.
this will be necessary to deal with negative IDs (if I choose to do that), and it'll also be necessary if I decide to do any shift hacks to merge ID/variant for block IDs, because we don't want such things to affect items before we're ready to deal with that.
This is a major change to the way block metadata is handled within the PM core. This separates variant metadata (which really ought to be part of the ID) from state metadata, and in a couple of cases flattens separate states of blocks together.
The result of this is that invalid variants can be much more easily detected, and additionally state handling is much cleaner since meta is only needed at the serialize layer instead of throughout the code.
This solves the age-old issue of PlayerInteractEvent firing twice when a player clicks a block with an item in the hand.
API changes:
- Removed PlayerInteractEvent constants LEFT_CLICK_AIR, RIGHT_CLICK_AIR and PHYSICAL.
- PlayerInteractEvent no longer fires when the player right-clicks the air.
- Added new event PlayerItemUseEvent.
This brings two plugin-breaking changes: AsyncTask->onCompletion() and AsyncTask->onProgressUpdate() no longer accept Server parameters.
This now allows for the functionality of AsyncPool and AsyncTask to be tested outside of a Server.
it's the generator's responsibility to know about the seed, not the chunkmanager's. This now reduces the complexity of implementing and using a chunkmanager.
it's no longer necessary to force-write these, since the NBT is now ephemeral. Any tag type mismatches should be dealt with on read, after which the original tag will be discarded anyway.
this was causing any items set into the hand during these events _at all_ to get overwritten, rather than just tools. That's a bit of a problem for buckets because buckets rely on a bad hack to handle the modified items.
This doesn't fix the tools bug, but that's a job for another time.
openssl_digest() is TWICE as fast as hash() on my machine for the same data and same algorithm. I can only guess that OpenSSL is more optimized than PHP ext/standard :)
Async compression and broadcasts are now reliable and don't have race condition bugs.
This features improved performance and significantly reduced bandwidth wastage.
Reduce Level broadcast latency by ticking network after levels. This ensures that session buffers get flushed as soon as possible after level tick, if level broadcasts were done.
this should never be called for a player with an empty username (because data isn't saved unless the player was spawned) and the instanceof is laughable.
the same behaviour can be achieved by cancelling the event and setting the held item manually. Allowing this to be changed increases the complexity of dealing with survival block picking.
this should fix forms not working during PlayerJoinEvent, and also removes the spurious PlayerItemHeldEvent firing on spawn bug.
The player MUST now send this packet. Bots take note.
This is a leftover from when it was necessary to pass complex data to the AsyncTask constructor in order to have it locally-stored. Since this has now been superseded by storeLocal(), it doesn't make sense for this parameter to exist anymore.
NetworkSession and some SessionHandlers hold cyclic refs to each other, stopping them getting destroyed. Unfortunately, these also reference the player, stopping that getting destroyed too.
The cycle garbage collector will deal with this, but it's best to get rid of the cyclic refs for immediate collection.
I considered renaming sendDataPacket() to dataPacket() to reduce the BC breaks, but the parameter set has changed, which might cause astonishing behaviour, so it's better to break it in a loud way. Also, this has a clearer name.
- Separated player handling and creation from network interfaces
- Rewire disconnects to make them not be recursive
- Batching now uses sessions instead of players
- Fixed DisconnectPacket getting sent to players who disconnect of their own accord
This also has the happy side effect of removing a cyclic dependency between Config and Server. There's only the dependency on MainLogger left to get rid of now.
Currently this can be used to attack the server by spamming requests for the same chunks forever. This commit prevents that by disconnecting the client if a chunk is requested more than 1 time. It is not necessary to allow more than 1 request per chunk, since RakNet should ensure that these are always delivered correctly.
This introduces several new session handlers, splitting up session handling into several new states:
- Login: Only allows handling the LoginPacket. This is the only time LoginPacket can be sent, and it'll be discarded when sent at any other time.
- Resource packs: Handles only the resource packs sequence (downloading packs and such). This is the only time ResourcePackClientResponse and ResourcePackChunkRequest will be handled.
- Pre-spawn: Only chunk radius requests are accepted during this state.
SimpleNetworkHandler handles all the "rest" of the logic that hasn't yet been separated out into their own dedicated handlers. There's also a NullNetworkHandler which discards all packets while it's active.
This solves a large number of issues with the security of the login sequence. It solves a range of possible DoS attacks and crashes, while also allowing great code simplification and cleanup.
This consolidates the Player entity construction and makes it more organized and consistent. There is of course a lot more work to do apart from this on player construction.
all the things we cared about in here don't exist anymore, so there's no sense in the handler still existing. It can be restored when we want to use the things it still does.
DataPacketSendEvent and DataPacketReceiveEvent will no longer capture BatchPackets
In most places strings are now used instead of DataPackets, to remove limitations on what data can be sent to a network interface
Removed CraftingManager's cyclic dependency on Server
There is a lot more work to do aside from this, but this commit is intended to clean up what is necessary to fix the handling of BatchPacket.
- remove onLoad(), onEnable(), onDisable()
- remove Config related methods
- remove getResource(), saveResource(), getResources()
did I troll any readers so far?
On a more serious note, these methods do not need to be declared in this interface because they are either hooks (`onLoad()`, `onEnable()`, `onDisable()`) or methods only used from within `PluginBase` and its children. They are not intended to be public API, and for this reason they don't need to be exposed in the interface.
This now computes BBs relative to 0,0,0 and then offsets them as appropriate. This requires less boilerplate code and also furthers the goal of separating block types from instances.
2018-06-21 19:58:28 +01:00
1700 changed files with 82734 additions and 76721 deletions
# Configuration for support-requests - https://github.com/dessant/support-requests
# Label used to mark issues as support requests
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:>
Thanks, but this issue tracker is 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).
Please see the [changelogs](/changelogs/${{ steps.get-pm-version.outputs.PM_VERSION_SHORT }}.md#${{ steps.get-pm-version.outputs.PM_VERSION_MD }}) for details.
Thanks, but this issue tracker is 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).
- A bash shell (git bash is sufficient for Windows)
- [`git`](https://git-scm.com) available in your shell
- PHP 7.3 or newer available in your shell
- PHP 8.0 or newer available in your shell
- [`composer`](https://getcomposer.org) available in your shell
## Custom PHP binaries
Because PocketMine-MP requires several non-standard PHP extensions and configuration, PMMP provides scripts to build custom binaries for running PocketMine-MP, as well as prebuilt binaries.
PocketMine-MP is an open source project, and contributions from the community are welcomed, as long as they comply with our quality standards and licensing.
## Creating an Issue
- If you are reporting a bug:
- **make sure that you are using the latest supported version** before opening an issue.
- **test it on a clean test server, WITHOUT PLUGINS**, to see if the issue still occurs. If not then it may be a plugin issue. Please also indicate the result of such tests.
- **[Search the issue tracker](https://github.com/pmmp/PocketMine-MP/issues?utf8=%E2%9C%93&q=is%3Aissue)** to check if anyone has already reported it, to avoid needlessly creating duplicate issues. Make sure you also check closed issues, as an issue you think is valid may already have been resolved.
- **Do not report plugin issues here.** If your issue is related to a plugin, contact the plugin's original author instead.
- **Support requests are not bugs.** Issues such as "How do I do this" are not bugs and will be closed. If you need help, please see [here](README.md#discussion) and do not misuse our issue tracker.
- **No generic titles** such as "Question", "Help", "Crash Report" etc. A good issue report provides a quick summary in the title. If you just got a crash report but you don't understand it, please look for a line starting with `Message`. It summarizes the bug.
- **Provide information in the issue body, not in the title.** No tags like `[BUG]` are allowed in the title, including `[SOLVED]` for solved issues.
- **No generic issue reports.** For bugs, it is the issue author's responsibility to provide us an issue that is **trackable, debuggable, reproducible, reported professionally and is an actual bug**.
<br>Valid issue reports must include instructions how to reproduce the issue or a crashdump/backtrace (unless the cause of the issue is obvious).
<br>**If you do not provide us with a summary or instructions on how to reproduce the issue, it will be treated as spam and will therefore be closed.**
<br>In simple words, if the issue cannot be properly confirmed to be valid or lacks required information, the issue will be closed until further information is provided.
- To express appreciation, objection, confusion or other supported reactions on pull requests, issues or comments on them, use GitHub [reactions](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) rather than posting an individual comment with an emoji only. This helps keeping the issue/pull request conversation clean and readable.
- If your issue is related to the PocketMine-MP website, forums, etc., please [talk to a human directly](README.md#discussion).
Code contributions must be submitted using [GitHub Pull Requests](https://github.com/pmmp/PocketMine-MP/pulls), where they will be reviewed by maintainers.
Small contributions (e.g. minor bug fixes) can be submitted as pull requests directly.
Larger contributions like feature additions should be preceded by a [Change Proposal](#rfcs--change-proposals) to allow maintainers and other people to discuss and decide if it's a good idea or not.
## Contributing
To contribute to the repository, [fork it on GitHub](https://github.com/pmmp/PocketMine-MP/fork), create a branch on your fork, and make your changes on your fork. You can then make a [pullrequest](https://github.com/pmmp/PocketMine-MP/pull/new) to the project to compare your branch to ours and propose your changestoour repository. We use the Pull Request system to allow members of the team to review changes before they are merged.
- [Creating a pull request from a fork](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)
### Licensing
By proposing a pull request to the project, you agree to your code being distributed within PocketMine-MP under the [LGPL license](LICENSE).
## Other things you'll need
- [git](https://git-scm.com/)
### Contribution standards
- **We enforce a very high standard for contributions**. This is because PocketMine-MP and its related projects are used very widely in production. While this might seem like we are being mean at times, **our priority is what is best for PocketMine-MP itself**.
We try to ensure that our project's codebase is as clean as possible and ensure that only top-quality material makes it through to PocketMine-MP itself.
- **If a contribution does not meet our standards, changes may be requested or the pull request may be closed.**
## Making a pull request
The basic procedure to create a pull request is:
1. [Fork the repository on GitHub](https://github.com/pmmp/PocketMine-MP/fork). This gives you your own copy of the repository to make changes to.
2. Create a branch on your fork for your changes.
3. Make the changes you want to make on this branch.
4. You can then make a [pull request](https://github.com/pmmp/PocketMine-MP/pull/new) to the project.
### Pull requests
- **Create a new branch for each pull request.** Do not create a pull request with commits that exist in another pull request.
## Pull request reviews
Pull requests will be reviewed by maintainers when they are available.
Note that there might be a long wait time before a reviewer looks at your PR.
Depending on the changes, maintainers might ask you to make changes to the PR to fix problems or to improve the code.
**Do not delete your fork** while your pull request remains open, otherwise you won't be able to make any requested changes and the PR will end up being declined.
### Requirements
The following are required as a minimum for pull requests. PRs that don't meet these requirements will be declined unless updated to meet them.
#### Licensing
PocketMine-MP is licensed under [LGPLv3 license](LICENSE).
By proposing a pull request, you agree to your code being distributed within PocketMine-MP under the same license.
If you take code from other projects, that code MUST be licensed under an LGPL-compatible license.
#### PRs should be about exactly ONE thing
If you want to make multiple changes, those changes should each be contributed as separate pull requests. **DO NOT** mix unrelated changes.
#### PRs must not include unnecessary/unrelated changes
Do not include changes which aren't strictly necessary. This makes it harder to review a PR, because the code diff becomes larger and harder to review.
This means:
- don't reformat or rearrange existing code
- don't change things that aren't related to the PR's objective
- don't rewrite existing code just to make it "look nicer"
- don't change PhpDocs to native types in code you didn't write
#### Tests must be provided
Where possible, PHPUnit tests should be written for new or changed code.
If that's not possible (e.g. for in-game functionality), the code must be tested manually and details of the tests done must be provided.
**Simply saying "Tested" is not acceptable** and will lead to your PR being declined.
#### Comments and documentation must be written in American English
English is the shared languages of all current maintainers.
#### Code must be in the PocketMine-MP style
It's your responsibility to ensure your code matches the formatting and styling of the rest of the code.
If you use PhpStorm, a `Project` code style is provided, which you can use to automatically format new code.
You can also use [`php-cs-fixer`](https://github.com/FriendsOfPHP/PHP-CS-Fixer) to format your code.
### Recommendations
- **Do not edit code directly on github.com.** We recommend learning how to use [`git`](https://git-scm.com). `git` allows you to "clone" a repository onto your computer, so that you can make changes using an IDE.
- **Use an IDE, not a text editor.** We recommend PhpStorm or VSCode.
- **Create a new branch on your fork for each pull request.** This allows you to use the same fork to make multiple pull requests at the same time.
- **Use descriptive commit titles.** You can see an example [here](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
- **Do not include multiple unrelated changes in one commit.** An atomic style for commits is preferred - this means that changes included in a commit should be part of a single distinct change set. See [this link](https://www.freshconsulting.com/atomic-commits/) for more information on atomic commits. See the [documentation on `git add`](https://git-scm.com/docs/git-add) for information on how to isolate local changes for committing.
- **Your pull request will be checked and discussed in due time.** Since the team is scattered all around the world, your PR may not receive any attention for some time.
- **It is inadvisable to create large pull requests with lots of changes** unless this has been discussed with the team beforehand. Large pull requests are difficult to review, and such pull requests may end up being closed. The only exception is when all features in the pull request are related to each other, and share the same core changes.
- **You may be asked to rebase your pull request** if the branch becomes outdated and/or if possibly conflicting changes are made to the target branch. To see how to do this, read [this page](https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request).
- **Details should be provided of tests done.** Simply saying "Tested" or equivalent is not acceptable.
### Code contributions
- **Avoid committing changes directly on GitHub. This includes use of the web editor, and also uploading files.** The web editor lacks most useful GIT features and **should only be used for very minor changes**. It is immediately clear if the web editor has been used, and if so the PR is more likely to be rejected. If you want to make serious contributions, **please learn how to use [GIT version control](https://git-scm.com/)**.
- **Do not copy-paste code**. There are potential license issues implicit with copy-pasting, and copy-paste usually indicates a lack of understanding of the actual code. Copy-pasted code is obvious a mile off and **any PR like this is likely to be closed**. If you want to use somebody else's code from a Git repository, **use [GIT's cherry-pick feature](https://git-scm.com/docs/git-cherry-pick)** to cherry-pick the commit. **Cherry-picking is the politer way to copy somebody's changes** and retains all the original accreditation, so there is no need for copy-pasted commits with descriptions like `Some code, thanks @exampleperson`.
- **Make sure you can explain your changes**. If you can't provide a good explanation of changes, your PR may be rejected.
- **Code should use the same style as in PocketMine-MP.** See [below](#code-syntax) for an example.
- **The code must be clear** and written in English, comments included.
- **Do not make large pull requests without an RFC.** Large changes should be discussed beforehand using the [RFC / Change Proposal](#rfcs--change-proposals) process. Large changes are much harder to review and are more likely to be declined if maintainers don't have a good idea what you're trying to do in advance.
- **Do not copy-paste code**. There are potential license issues implicit with copy-pasting, and copy-paste usually indicates a lack of understanding of the actual code. Copy-pasted code is obvious a mile off and **any PR like this is likely to be closed**. If you want to use somebody else's code from a Git repository, **use [GIT's cherry-pick feature](https://git-scm.com/docs/git-cherry-pick)** to cherry-pick the commit.
**Thanks for contributing to PocketMine-MP!**
## RFCs / Change Proposals
Change Proposals are issues or discussions which describe a new feature proposal or behavioural change.
They are used to get feedback from maintainers and the community about an idea for a change, to decide whether or not it's a good idea.
### Submitting an RFC
RFCs should be submitted using Issues or Discussions.
RFCs _can_ be submitted as pull requests if you've already written the code, but this is not recommended, since it's not guaranteed that an RFC will pass, in which case your effort would be wasted.
### Code Syntax
RFCs should include the following:
- A summary of what you want to change
- Why you want to change it (e.g. what problems it solves)
- Alternative methods you've considered to solve the problem. This should include any possible ways that what you want can be done without the change.
It is mainly [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md) with a few exceptions.
### Voting on RFCs
Community members can vote on RFCs. This gives maintainers an idea of how popular the idea is.
Votes can be cast using :+1: and :-1: reactions.
- Opening braces MUST go on the same line, and MUST NOT have spaces before.
-`else if` MUST be written as `elseif`. _(It is in PSR-2, but using a SHOULD)_
- Control structure keywords or opening braces MUST NOT have one space before or after them.
- Code MUST use tabs for indenting.
- Long arrays MAY be split across multiple lines, where each subsequent line is indented once.
- Files MUST use only the `<?php` tag.
- Files MUST NOT have an ending `?>` tag.
- Code MUST use namespaces.
- Strings SHOULD use the double quote `"` except when the single quote is required.
- All code SHOULD have parameter and type declarations where possible.
- Strict types SHOULD be enabled on new files where it is sensible to do so.
- All constant declarations SHOULD be preceded by a visibility modifier.
**Please don't downvote without providing a reason why!**
```php
<?php
### Implementing RFCs
Anyone can write the code to implement an RFC, and submit a pull request for it. It doesn't have to be the RFC author.
<ahref="https://github.com/pmmp/PocketMine-MP/releases"><imgsrc="https://img.shields.io/github/v/tag/pmmp/PocketMine-MP?label=release&logo=github"alt="GitHub tag (latest semver)"/></a>
<ahref="https://hub.docker.com/r/pmmp/pocketmine-mp"><imgsrc="https://img.shields.io/docker/v/pmmp/pocketmine-mp?logo=docker&label=image"alt="Docker image version (latest semver)"/></a>
**DO NOT report vulnerabilities on the GitHub issue tracker.**
GitHub is public and anyone can see the issues you post on the issue tracker, including people who would exploit vulnerabilities for their own gain.
**WARNING: You may put live servers at risk by reporting a vulnerability on the GitHub issue tracker.**
**Contact us** by sending an email to [**team@pmmp.io**](mailto:team@pmmp.io?subject=Security%20Vulnerability%20in%20PocketMine-MP). Include the following information:
- Version of PocketMine-MP
- Detailed description of the vulnerability (e.g. how to exploit it, what the effects are)
Please note that we can't guarantee a reply to every email.
## FAQ
### Do you offer a bug bounty?
No.
### How soon can I expect a fix for a vulnerability I've reported?
This depends on the nature of the problem. We can't provide any general ETA (nor would it be wise to provide one).
In general, it depends on when developers have time to look into the problem, how complex the problem is to fix, and how many users it impacts.
When a fix for a severe vulnerability is pushed, a patch release for the target version will usually be released within 24 hours so that users can update.
@ -23,3 +23,18 @@ Plugin developers should **only** update their required API to this version if y
-`/plugins`, `/whitelist list`, `/banlist` and `/list` now show output in alphabetical order.
- Some `pocketmine\event` APIs which accept arrays now have more robust type checking, fixing type errors caused by plugin input occurring in core code.
-`Attribute::getAttributeByName()` is now aware of the `minecraft:lava_movement` attribute.
# 3.14.2
- Exception stack traces are now logged as CRITICAL. It's hoped that users will recognize that they are just as important as the error message and not leave them out when asking for help with errors on Discord.
-`TaskScheduler` no longer accepts tasks that already have a handler. This fixes undefined behaviour which occurs when scheduling the same task instance twice, but it does break plugins such as **MyPlot** which unintentionally used this buggy behaviour.
- Players will now correctly receive the needed number of spawn chunks if they are teleported between `PlayerLoginEvent` and `PlayerJoinEvent`. This fixes a bug that could occur when teleporting players in delayed tasks between login and join.
-`PlayerRespawnEvent->setRespawnPosition()` now throws an exception if the provided `Position` has an invalid world associated with it (null or unloaded).
- Fixed a crash that occurred when stats reporting was enabled.
# 3.14.3
- Fixed deprecation error when running `/whitelist list` on PHP 7.4.
- Fixed podzol breaking animation being incorrect (incorrect hardness).
-`Entity::getSaveId()` now reports the class name in the message thrown for unregistered entities.
- Fixed `CraftingManager->validate()` producing different results when called multiple times for the same transaction.
- Fixed various issues with batch-crafting items using the recipe book and shift-clicking.
-`tests/plugins/PocketMine-DevTools` submodule has been renamed to `tests/plugins/DevTools`.
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.15.0
- Added support for Minecraft: Bedrock Edition 1.16.20.
- Removed compatibility with 1.16.0.
## Known issues (please don't open issues for these)
- Walls don't connect to each other
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
- New blocks, items & mobs aren't implemented
- Nether doesn't exist
# 3.15.1
- Fixed various PHP 7.4 compatibility issues in Composer dependencies (primarily callback-validator).
- Fixed LevelDB worlds with corrupted `level.dat` crashing the server instead of failing gracefully.
- Fixed error spam when using strings for layers in flatworld presets (`e.g. bedrock,3xdirt,grass`).
- Fixed blocks not getting updated properly on explosions.
- Fixed `BlockGrowEvent` not being called when sugarcane grows.
- Potato crops now drop poisonous potatoes when harvested.
- Fixed the wrong number of potatoes being dropped when harvesting potato crops.
- Players no longer get pullbacks when sprinting on slabs, stairs and various other blocks when `player.anti-cheat.allow-movement-cheats` is set to `false`. (This bug has been around for over 5 years, so many of you will be used to its existence.)
- Fixed entity collision box calculation not taking clip distance into account.
- Entities now step up the correct height of the target block, instead of jumping into the air 0.6 blocks and falling back down.
# 3.15.2
- Fixed issues with preloading `SubChunk`.
-`/gc` and automatic garbage collection will now release unused heap blocks back to the OS. Previously, the PHP process might hold onto these blocks indefinitely even when not used, causing elevated real memory usage.
- Added some documentation to `FurnaceBurnEvent`.
# 3.15.3
- Fixed fall damage accumulation over continuous knockbacks (e.g. combo attacks in PvP).
- Fixed a bug in `Human->addXp()` that would cause a crash when saving player data.
-`Human->addXp()` will no longer modify the target's total XP if `PlayerExperienceChangeEvent` was cancelled.
-`AsyncPool->getTaskQueueSizes()` has been added to allow external detection of async pool overload. This is planned to be implemented as a core feature in the future, but it hasn't been done yet.
-`BaseInventory->canAddItem()` behaviour now matches `addItem()` by considering the max stack size of the given item.
- Fixed a bug in generator options handling for worlds loaded via `pocketmine.yml`. This fix has the following side effects:
- It's now possible to provide generator options as an `options` key when loading a world via `pocketmine.yml`.
- If generator options are not provided, the options from `server.properties` will be used, instead of using an empty preset. (It's not clear whether this is desired behaviour, but it was clearly intended, since there is code to do this which was broken until this release. As such, this behaviour is subject to change in the future.)
- Fixed a bug in region-based world loading where some files without filename extensions and names containing a region filename extension (e.g a file named `amca` in a McRegion world) would cause the world not to load. These files are now ignored.
- Default network compression level has been lowered to 6, due to level 7 being 25% more expensive for only a marginal improvement in bandwidth.
- Fixed a performance issue with chunk requesting when players trigger chunk generation on first join.
- Setup wizard will now always show IP information, even if the user chose to skip the setup wizard when prompted. (This doesn't affect `--no-wizard` in any way.)
-`Maximum memory (system)` is no longer reported in `/status` due to having a misleading output (it was the same as the current memory usage).
- The `Player Chunk Send` timer on timings reports now actually reports measurements of chunk sending, not chunk loading.
- A new parent timer `World Load` has been added to timings reports, which aggregates timings from `syncChunkLoad` and subtimings from all worlds.
# 3.15.4
- Fixed a bug in the inventory transaction system that caused the server to freeze under some circumstances.
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.16.0
- Added support for Minecraft: Bedrock Edition 1.16.100.
- Removed compatibility with earlier versions.
- Added new custom composer commands `make-server` and `make-devtools` to ease setting up a development environment and building the server.
## Known issues (please don't open issues for these)
- Walls don't connect to each other
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
- New blocks, items & mobs aren't implemented
- Nether doesn't exist
# 3.16.1
- Fixed incorrect encoding of skins in the protocol.
-`/version` no longer crashes when a plugin provides `string[]` for the `author` field in `plugin.yml`.
-`author` in `plugin.yml` now accepts arrays, just like `authors`.
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.17.0
- Added support for Minecraft: Bedrock Edition 1.16.200.
- Removed compatibility with earlier versions.
## Known issues (please don't open issues for these)
- Walls don't connect to each other
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
- New blocks, items & mobs aren't implemented
- Nether doesn't exist
# 3.17.1
- Fixed some instances of plugin-caused crashes not being detected (eval()'d code, custom plugin paths).
- Server uptime is now included in crash reports.
- Hoes now take damage when used to break sponges.
- Using lava as fuel in a furnace now leaves behind an empty bucket.
# 3.17.2
- Fixed region header corruption when chunks with larger-than-expected lengths are found. These chunks are now treated as corrupted, instead of automatically attempting to salvage them (which usually fails anyway).
-`RegionLoader->removeChunk()` now allows the space used by the removed chunk to be reused by future region saves.
- Extracted `Living->applyConsumptionResults()` from `Living->consumeObject()` (preparation for a future bug fix).
# 3.17.3
- Improved performance of chunk loading in Region-based worlds.
- Improved performance of region header validation in Region-based worlds (indirect improvement to chunk loading performance).
- Fixed some PHP 8.0 language-level compatibility issues.
- Source installations will now exit with an error when Composer dependencies are not in sync with the current Git revision. Now, it's required to run `composer install` after every git pull to make sure the correct dependency versions are installed.
# 3.17.4
- Removed `readline` support. This hasn't been maintained for many years, never worked correctly, and isn't thread-safe in any case.
- Fixed false-positives of region corruption in Region-based worlds (outdated file stat cache).
- Fixed more deprecation warnings on PHP 8.0 (optional parameter before required).
-`CraftItemEvent->getInputs()` now returns a list starting at offset 0, instead of random offsets. (Note that the contents still won't be ordered.)
-`CraftItemEvent->getOutputs()` now returns a list starting at offset 0, instead of random offsets. (Note that the contents still won't be ordered.)
- Fixed a bug that broke synchronized building, bridging, towering and more.
- Objects in memory dumps no longer show inherited properties multiple times.
# 3.17.5
- Reduced CPU wastage by the logger thread.
- Fixed LevelDB deprecation errors on PHP 8.0.
- Added some protocol changes for 1.16.200 which were previously overlooked.
- Player XUIDs are now tracked. If a player's XUID does not match the previously recorded XUID when they next join the server, they will be kicked. This can be disabled by the `player.verify-xuid` setting in `pocketmine.yml`.
-`BUILDING.md` now has a note about `build/server-phar.php`'s compression bug (a bug in PHP).
# 3.17.6
- Fixed core race conditions that could have led to server freezes (race conditions in pmmp/Snooze).
- The log message about Xbox Live authentication being enabled has been reduced to INFO, and the tip on how to turn it off removed (disabling it should usually only be done by power users anyway).
- Fixed `PlayerMoveEvent->getFrom()` returning incorrect results for players who experienced movement reversions.
- Fixed a bug in `ResourcePackClientResponsePacket` decoding that caused unexpected results when decoding the packet twice.
- XUID verification now compares XUIDs against players who are already on the server to detect mismatches to avoid unnecessary loading of playerdata.
- Fixed an inventory duplication bug which could occur when the same player joined with two devices at the same time.
- Fixed cursor item not being synced on inventory transaction rollbacks.
- Fixed items with TAG_Float in their NBT not being able to be moved around in the inventory.
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.18.0
- Added support for Minecraft: Bedrock Edition 1.16.210.
- Removed compatibility with earlier versions.
## Known issues (please don't open issues for these)
- Walls don't connect to each other
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
- New blocks, items & mobs aren't implemented
- Nether doesn't exist
- Items can't be removed from item frames in Survival mode
# 3.18.1
- UPnP is now supported on all platforms instead of just Windows. Note that it's still experimental. Please file issues for any bugs that you find.
- Fixed server joining when default game mode is set to Spectator mode.
- Fixed items not being able to be removed from item frames in Survival mode.
- Fixed field order in ClientCacheBlobStatusPacket (hits and misses were inverted).
- Fixed a deadlock that could occur when MainLogger->syncFlushBuffer() was used (usually only used during exception logging).
- Updated constants for various things in the protocol.
# 3.18.2
- Fixed `InventoryCloseEvent` not being called on server-initiated inventory closures.
-`PlayerToggleFlightEvent` may now be pre-cancelled if the player attempted to enable flight when flying was not allowed. This replaces the previous behaviour of kicking the player.
- Fixed being unable to change the item in hand from the inventory window when looking at an entity.
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.19.0
- Added support for Minecraft: Bedrock Edition 1.16.220.
- Removed compatibility with earlier versions.
## Known issues (please don't open issues for these)
- Walls don't connect to each other
- Pumpkin and melon stems may not connect to their corresponding pumpkin/melon
- New blocks, items & mobs aren't implemented
- Nether doesn't exist
# 3.19.1
- Fixed some particles not working since 1.16.220.
- Fixed issues with creative inventory items appearing in the wrong places since 1.16.220.
-`Item->removeEnchantment()` now removes the `ench` tag from item NBT when removing the only enchantment on an item.
- Fixed temporary memory leak of repeating tasks which cancelled themselves during their `onRun()` handler (they were pushed back onto the task queue even though cancelled, and only removed at their next attempted repeat).
# 3.19.2
- Signs can now only be edited by the player who placed them. They will become finalized if the chunk containing them is unloaded and reloaded, or if the creating player quits the server.
# 3.19.3
- Fixed `Worker->quit()` returning without stopping the thread.
- Added some protocol constants in `SetDisplayObjectivePacket`.
- Fixed possible client crash caused by `CraftingDataPacket`.
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.20.0
- Added support for Minecraft: Bedrock Edition 1.17.0
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.21.0
- PHP 7.4 is now required as a minimum.
- A workaround for player movement added in 1.14.30 has been removed.
# 3.21.1
- Fixed so-called 'pot lag' - a bug that could occur when using items while rapidly switching hotbar slots.
- Plugins in crashdumps are now ordered alphabetically for easier reading.
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.22.0
- Added support for Minecraft: Bedrock Edition 1.17.10.
- Removed compatibility with earlier versions.
# 3.22.1
- Added a giant yellow startup warning if using OPcache JIT on PHP 8.0. JIT is currently considered highly unstable and not recommended for production use.
- When using a bad PHP binary, the bootstrap will now report the used `php.ini` path. This can be useful for debugging issues with extension loading when the wrong `php.ini` file is loaded for some reason.
- Fixed `start.cmd` causing the wrong `php.ini` to be loaded on Windows when a global PHP installation is used.
- A debug message is now logged containing expected vs. actual XUID of players when an XUID mismatch is detected.
- Improved the documentation for `Player->getUniqueId()`.
- Fixed a mistake in the documentation of `PlayerAuthInputFlags`.
- Fixed incorrect encoding of `NpcDialoguePacket`.
# 3.22.2
- PHP 8.0 is now the primary supported version. PHP 7.4 is still supported for now, but it will be dropped in the coming weeks. It's recommended to start testing your servers on 8.0 now so you're ready.
- Fixed items in the crafting grid getting deleted on server-side disconnect or session timeout.
- A warning is now logged on startup if a debug build of PHP is used to run the server (because it has a significant performance impact).
- GitHub Actions is now used to build new releases, instead of Jenkins. You can see build logs [here](https://github.com/pmmp/PocketMine-MP/actions/workflows/draft-release.yml).
# 3.22.3
- Fixed a bug in the release build of 3.22.2 which caused the crash archive to reject all crashdumps.
- Fixed possible server crash during player spawning.
# 3.22.4
- Fixed a bug which broke the build of 3.22.3.
# 3.22.5
- Added a workaround for polyfilled solid-colour Persona skin replacements turning into a corrupted mess (caused by https://bugs.mojang.com/browse/MCPE-130275).
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.23.0
- Added support for Minecraft: Bedrock Edition 1.17.30.
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.24.0
- PHP 8.0 is now required as a minimum.
- Fixed stats reporting checking the wrong `pocketmine.yml` property.
- Fixed `Projectile->move()` not respecting the given `dx`/`dy`/`dz` and using its own motion instead.
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.25.0
- Added support for Minecraft: Bedrock Edition 1.17.40.
- Removed compatibility with earlier versions.
# 3.25.1
- Fixed autosave bug that caused unmodified chunks to be saved at least once (during the first autosave after they were loaded).
-`Entity->spawnTo()` now has an additional sanity check for matching worlds (might expose a few new errors in plugins).
- Fixed a missing field in `CraftRecipeAuto` item stack request type.
# 3.25.2
- Now analysed using level 9 on PHPStan 1.0.0.
-`ext-pthreads` v4.0.0 or newer is now required.
- Fixed crash in `Player->showPlayer()` when the target is not in the same world.
-`Human->setLifetimeTotalXp()` now limits the maximum value to 2^31.
- Fixed players, who died in hardcore mode and were unbanned, getting re-banned on next server join.
#Compression level used when sending batched packets. Higher = more CPU, less bandwidth usage
compression-level:7
compression-level:6
#Use AsyncTasks for compression. Adds half/one tick delay, less CPU load on main thread
async-compression:false
#Experimental, only for Windows. Tries to use UPnP to automatically port forward
#Experimental. Use UPnP to automatically port forward
upnp-forwarding:false
#Maximum size in bytes of packets sent over the network (default 1492 bytes). Packets larger than this will be
#fragmented or split into smaller parts. Clients can request MTU sizes up to but not more than this number.
max-mtu-size:1492
#Enable encryption of Minecraft network traffic. This has an impact on performance, but prevents hackers from stealing sessions and pretending to be other players.
#DO NOT DISABLE THIS unless you understand the risks involved.
enable-encryption:true
debug:
#If > 1, it will show debug messages in the console
@ -100,13 +103,13 @@ debug:
player:
#Choose whether to enable player data saving.
save-player-data:true
anti-cheat:
#If false, will try to prevent speed and noclip cheats. May cause movement issues.
allow-movement-cheats:true
#If true, checks that joining players' Xbox user ID (XUID) match what was previously recorded.
#This also prevents non-XBL players using XBL players' usernames to steal their data on servers with xbox-auth=off.
verify-xuid:true
level-settings:
#The default format that levels will use when created
default-format:pmanvil
default-format:leveldb
chunk-sending:
#To change server normal render distance, change view-distance in server.properties.
@ -120,8 +123,9 @@ chunk-ticking:
per-tick:40
#Radius of chunks around a player to tick
tick-radius:3
light-updates:false
clear-tick-list:true
#Number of blocks inside ticking areas' subchunks that get ticked every tick. Higher values will accelerate events
#like tree and plant growth, but at a higher performance cost.
blocks-per-subchunk-per-tick:3
#IDs of blocks not to perform random ticking on.
disable-block-ticking:
#- 2 # grass
@ -151,7 +155,6 @@ auto-updater:
enabled:true
on-update:
warn-console:true
warn-ops:true
#Can be development, alpha, beta or stable.
preferred-channel:stable
#If using a development version, it will suggest changing the channel
critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html.");
$this->register(newJukebox(newBID(Ids::JUKEBOX,0,ItemIds::JUKEBOX,TileJukebox::class),"Jukebox",newBlockBreakInfo(0.8,BlockToolType::AXE)));//TODO: in PC the hardness is 2.0, not 0.8, unsure if this is a MCPE bug or not
$this->register(newOpaque(newBID(Ids::OBSIDIAN,0),"Obsidian",newBlockBreakInfo(35.0/* 50 in PC */,BlockToolType::PICKAXE,ToolTier::DIAMOND()->getHarvestLevel(),6000.0)));
$this->register(newOpaque(newBID(Ids::QUARTZ_BLOCK,Meta::QUARTZ_SMOOTH),"Smooth Quartz Block",$quartzBreakInfo));//TODO: this has axis rotation in 1.9, unsure if a bug (https://bugs.mojang.com/browse/MCPE-39074)
$this->register($chiseledStoneBrick=newOpaque(newBID(Ids::STONEBRICK,Meta::STONE_BRICK_CHISELED),"Chiseled Stone Bricks",$stoneBreakInfo));
$this->register(newInfestedStone(newBID(Ids::MONSTER_EGG,Meta::INFESTED_STONE_BRICK_CHISELED),"Infested Chiseled Stone Brick",$infestedStoneBreakInfo,$chiseledStoneBrick));
$this->register($crackedStoneBrick=newOpaque(newBID(Ids::STONEBRICK,Meta::STONE_BRICK_CRACKED),"Cracked Stone Bricks",$stoneBreakInfo));
$this->register(newInfestedStone(newBID(Ids::MONSTER_EGG,Meta::INFESTED_STONE_BRICK_CRACKED),"Infested Cracked Stone Brick",$infestedStoneBreakInfo,$crackedStoneBrick));
$this->register($mossyStoneBrick=newOpaque(newBID(Ids::STONEBRICK,Meta::STONE_BRICK_MOSSY),"Mossy Stone Bricks",$stoneBreakInfo));
$this->register(newInfestedStone(newBID(Ids::MONSTER_EGG,Meta::INFESTED_STONE_BRICK_MOSSY),"Infested Mossy Stone Brick",$infestedStoneBreakInfo,$mossyStoneBrick));
$this->register(newStair(newBID(Ids::MOSSY_STONE_BRICK_STAIRS,0),"Mossy Stone Brick Stairs",$stoneBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(newSlab(BlockLegacyIdHelper::getStoneSlabIdentifier(3,Meta::STONE_SLAB3_END_STONE_BRICK),"End Stone Brick",$stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(newSlab(BlockLegacyIdHelper::getStoneSlabIdentifier(3,Meta::STONE_SLAB3_SMOOTH_RED_SANDSTONE),"Smooth Red Sandstone",$stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(newSlab(BlockLegacyIdHelper::getStoneSlabIdentifier(4,Meta::STONE_SLAB4_CUT_RED_SANDSTONE),"Cut Red Sandstone",$stoneSlabBreakInfo));
$this->registerSlabWithDoubleHighBitsRemapping(newSlab(BlockLegacyIdHelper::getStoneSlabIdentifier(4,Meta::STONE_SLAB4_MOSSY_STONE_BRICK),"Mossy Stone Brick",$stoneSlabBreakInfo));
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.