Use existing isPlayerPlaced value to track who placed a block #243
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What is this?
This is a proof-of-concept of using the isPlayerPlaced value to store an identifier for the player who placed the block.
The existing behavior is to set that value to "1" if placed by a player... and then do nothing with the actual integer stored.
Since we're already storing four bytes per player-placed block, why not use them?
Why make this change?
This change allows for the easy creation of a self_placed filter, which I'll include in a PR to the libreforge repo shortly.
What good is a self_placed filter?
How it works
This change assigns each player a local ID, and then uses that ID instead of the value "1" for the isPlayerPlaced value.
Local ID is a single INT stored stored on the PlayerProfile. Storing it on the player profile makes it a proxy value for UUID.
Why not use UUID instead of a local ID?
If additional memory use isn't a concern, UUIDs are the most robust solution. However, using a UUID here would increase storage space used by isPlayerPlaced 4x.
Doing it with local IDs, as this PR does, allows us to use the existing value and thus has no increase in per-block storage use.
Given the size of a signed 4-byte integer, a server won't run out of local IDs until Minecraft sells 2 billion copies and all of those copies come to play on a specific server.
Why not rely on the anti-grief integration?
The anti-grief integration only tracks who has permission to modify a given block. Not who placed it in the first place. Even if we were to modify the integration, not every anti-grief plugin implements a "who placed this block" function.
And again, we already store a value here. This is just making use of it.
Performance Analysis
The existing behavior is to write to the chunk's profile each time a player places a block. This behavior is unchanged.
There is now an additional read from the player's profile when placing blocks, to determine the player's local ID. Depending on how that read occurs in the code (I haven't read deeply yet, but I'm assuming it's memoized somewhere so it's not hitting the DB/Disk every read) this should have negligable impact.
Backwards Compatibility
This change doesn't break any existing behavior.
Before this PR, worlds with blocks marked by isPlayerPlaced use the value 1 to denote their placement, and no value if they were not player placed. I've ensured that the local player IDs start at 2, so that there's no conflict on migrating versions.
There's also no conflict if the server downgrades from this version; the actual value set by isPlayerPlaced is ignored prior to this PR.