Make ^ support nbt (properly) - #2734
Conversation
a572827 to
9c974cf
Compare
me4502
left a comment
There was a problem hiding this comment.
Thanks for this. I've left a comment around API breakages. I haven't reviewed the actual parser itself as the diff is broken currently by the rename.
Also as this is adding behaviour, this should be targeting master, not 7.3.x.
| import java.util.stream.Stream; | ||
|
|
||
|
|
||
| public class PartiallyApplyingPatternParser extends InputParser<Pattern> { |
There was a problem hiding this comment.
Renaming this class would be an API break, so it'd need to retain its original name, or duplicate it and deprecate the old one.
There was a problem hiding this comment.
What is the rule for API breaks/changes? Am I allowed to change behaviour in a potentially breaking way (this is) and still maintain the same name/API? Or do I need to provide a fully backwards-compatible implementation?
There was a problem hiding this comment.
I created a deprecated legacy version, that should behave like before. Do I need to do the same for the two Patterns that I changed?
Is there some documentation on what needs to stay API compatible?
There was a problem hiding this comment.
Typically as long as it's binary compatible and works vaguely as expected it should be fine. Slight behaviour changes can happen IMO.
| @Override | ||
| public BaseBlock applyBlock(BlockVector3 position) { | ||
| BlockState oldBlock = getExtent().getBlock(position); | ||
| BaseBlock oldBlock = getExtent().getFullBlock(position); |
There was a problem hiding this comment.
Have you tested how well this performs? This fundamentally means the pattern is doing a lot more work per-block.
Also, have you tested how this behaves when set to another block with a block entity of a different type, with conflicting data? Eg, change a chest with items to a jukebox and make sure it doesn't explode?
There was a problem hiding this comment.
It does a lot more (in some cases unavoidable) work. I did not do large scale testing where performance issues would become apparent. I will think about how we can avoid incurring a performance penalty (if there is one, I'll test that) for blocks that can't have NBT or when NBT is overwritten anyway.
If it breaks something, it can already break with the vanilla /data command. But it and the data command, in fact, are able to break a lot of (as far as I have tested only non-vanilla) blocks, and AFAICT, there is not much we could do about it. We could maintain a gigantic database of sanitizers, one for every block with tile entity in every mod, plead to mod devs to sanitize their NBT properly, or we could prevent the game from flushing to disk until after the command finished, to prevent game-cashing NBT from corrupting worlds, at the expense of possibly prohibitive RAM use.
There was a problem hiding this comment.
I wasn't able to detect any performance impact, which honestly surprised me. Not sure if my testing was flawed.
The performance impact seems, at least on my PC, to be completely drowned by IO for huge edits, and be undetectably small for smaller ones.
If you manage to find a scenario in which my changes have a significant performance impact, I'd be happy to take another look.
There was a problem hiding this comment.
The case where this would likely have the most impact is when the selection has a large amount of complex NBT data in it, as the change basically leads to reading that data from the world.
Although tbh AFAICT this change here is mostly a bugfix anyway, so if it's performant it might be fine to PR separately to version/7.4.x
There was a problem hiding this comment.
I tried fitting as many barrels with items in the loaded chunks as my heap size allows (16GiB) to avoid the IO bottlenecks I experienced in my previous testing, and replacing them with and without the changes in this PR. And while the time till the replaced ... blocks message didn't meaningfully change, the time till the game became responsive again did significantly increase with these changes (between 30% and 50%).
I see a similar slowdown merging NBT vs. setting NBT. So it seems that reading NBT for each block indeed can cause a significant difference, that will likely increase with more complex NBT (e.g. complex items in the barrels).
I will try to include an optimisation that makes the respective patterns skip reading & writing NBT if that is unnecessary. This should at least allow users experiencing performance issues to just specify {=} and get the previous performance back, at the cost of the previous behaviour.
|
I have concerns about the exact syntax here, I don't think we should allow As it stands, |
|
While I understand you concern, I have some concerns with merge only for The current syntax allows for simply including If we do merge only, we need to add a different way to have I'd suggest following to make it more consistent, without introducing a new prefix: If you have a different idea on how that could be implemented more consistently, I'm very open to suggestions. |
9c974cf to
4f58081
Compare
|
I have changed it to merge by default and set with |
|
Does this PR also preserve sign and hanging sign text? If so, it will close #2546 |
4f58081 to
e2f2e19
Compare
Yes. Along with preserving chest/barrel contents, pot contents ... Updated the PR to current master. |
e2f2e19 to
5f39ada
Compare
|
Updated the MR to fix an issue with the command mentioned in #2998 I am not quite confident in the changes in StringUtils.parseListInQuotes, because I am unsure of the original intent of that method. |
a382de1 to
cda2816
Compare
me4502
left a comment
There was a problem hiding this comment.
Sorry it's been so long – I missed the initial changes you made after the reviews, and then with the uptick in MC update frequency/etc I haven't had a chance to look at the PR backlog outside of ones I was actively tracking.
I've replied to the comments, otherwise I'll let @octylFractal review the actual parser behaviour here. I'm a little apprehensive about the complexity of this parser at this point
| @Override | ||
| public BaseBlock applyBlock(BlockVector3 position) { | ||
| BlockState oldBlock = getExtent().getBlock(position); | ||
| BaseBlock oldBlock = getExtent().getFullBlock(position); |
There was a problem hiding this comment.
The case where this would likely have the most impact is when the selection has a large amount of complex NBT data in it, as the change basically leads to reading that data from the world.
Although tbh AFAICT this change here is mostly a bugfix anyway, so if it's performant it might be fine to PR separately to version/7.4.x
| import java.util.stream.Stream; | ||
|
|
||
|
|
||
| public class PartiallyApplyingPatternParser extends InputParser<Pattern> { |
There was a problem hiding this comment.
Typically as long as it's binary compatible and works vaguely as expected it should be fine. Slight behaviour changes can happen IMO.
68cef48 to
cce709b
Compare
cce709b to
a7abc4f
Compare
|
I added a Test to increase my confidence in the implementation of the PartiallyApplyingPatternParser, however, I had to add a couple of public getters to the Patterns for validation, and I am not sure if that is an acceptable in this project. If it isn't, I am open to any suggestions on how to do it better. Also, can I add a component test spanning the entire parsing logic? I am unsure if the Parsers interact correctly for nested/mixed Patterns. |
My implementation of #2733,
It adds ^{=nbt} support, integrated in current ^ support to allow replacing/keeping arbitrary parts of a block.
Additionally, adds {nbt} support for merging NBT tags into existing ones.
Examples:
//replace chest ^barrel will keep orientation and NBT intact and just replace the block type, keeping e.g. contents as-is.
//replace chest ^[facing=north] will make all chest face north, keeping their NBT intact.
//replace chest,barrel ^{=LootTable:"minecraft:chests/simple_dungeon"} will make both, chests and barrels contain dungeon loot, while removing any potential other NBT.
//set ^{=} deletes nbt from selection. (does not work for LootTable tags due to a bug in vanilla MC I can't link here or find again because mojangs bug tracker is completely broken)
//replace decorated_pot ^{LootTable:"minecraft:chests/simple_dungeon"} will make pots contain dungeon loot while keeping their pattern.
...