FAWE does not write into extent of edit session, but into world of extent
rainbowdashlabs opened this issue ยท 8 comments
Server Implementation
Paper
Server Version
1.19.3
Describe the bug
First: This bug does not occur when using WorldEdit. It only occurs when using FAWE
When creating an ImmutableWorld Extent which blocks setting of a block and modifying the world in general, FAWE still writes into the world itself instead of the extend provided for the edit session.
None of the setBlock methods of the extent is called. I suspect that FAWE directly writes into the chunks which would makes sense considering how fawe works, but this causes that the extent is used to retrieve the chunks but not to write the changes.
Since the original extent is wrapped into an SingleThreadQueueExtent and this implements how the chunk setters are retrieved, there is no real way to prevent writing into the chunks from api side.
Case 1
EditSession with normal world.
PasteOperation into EditSession as Extent
Result: Schematic gets pasted into the world (Expected)
Case 2
EditSession with ImmutableWorld.
PasteOperation with ImmutableWorld as Extent
Result: Schematic does NOT get paste into the world (Expected)
Case 3
EditSession with ImmutableWorld.
PasteOperation with EditSession as Extent
Result: Schematic gets pasted into the world (Unexpected)
To Reproduce
I created a minimal working example:
https://github.com/eldoriarpg/we-playground
- Install the plugin
- Execute
/wetest <case>
to execute one of the cases described above.
Expected behaviour
That FAWE writes into the provided extent and not into the chunks of the extent as it seems.
Screenshots / Videos
No response
Error log (if applicable)
No response
Fawe Debugpaste
https://athion.net/ISPaster/paste/view/973182bf68674dfc91006cc50d54d6c4
Fawe Version
FastAsyncWorldEdit-Bukkit-2.5.3-SNAPSHOT-370
Checklist
- I have included a Fawe debugpaste.
- I am using the newest build from https://ci.athion.net/job/FastAsyncWorldEdit/ and the issue still persists.
Anything else?
No response
You need to override all methods present in FAWE's extent class.
What different methods does FAWE use to write blocks from a paste operation into an extent compared to WorldEdit? In the end it should always narrow down to setBlock(int, int, int, T)
, but this method is not called. Neither is setBlock(BlockVector3, B, SideEffectSet)
. The setBlocks methods all delegate down to the setBlock(int, int, int, T)
method. There is no reason to override all methods. Overriding methods involved in changing blocks should be enough already, but isn't as it seems.
Blindly overriding methods of the Extent class should not be necessary. I also added an override for the replaceBlocks
and setBlocks
, but those are not called as well
Okay let me add some more information:
I have a ImmutableWorld
Extent, which extends BukkitWorld
. This Extent overrides both setBlock methods.
Case 1
EditSession with normal world.
PasteOperation into EditSession as Extent
Result: Schematic gets pasted into the world (Expected)
Case 2
EditSession with ImmutableWorld.
PasteOperation with ImmutableWorld as Extent
Result: Schematic does NOT get paste into the world (Expected)
Case 3
EditSession with ImmutableWorld.
PasteOperation with EditSession as Extent
Result: Schematic gets pasted into the world (Unexpected)
I added the three cases into the sample plugin. Maybe this makes it more clear what the issue here is @dordsor21
There should be no difference whether the ImmutableWorld Extent is wrapped in the edit session or directly provided to the Operation. In the end FAWE should attempt to write into the ImmutableWorld in both cases.
I think that the issue is slightly poorly named. It seems to me that the issue that "FAWE ignores the setBlock method in subclass of world" which is exactly expected behaviour; were FAWE to set each block to the world individually there would be much less performance gain over regular worldedit. The methodology used here to "block" edits is completely contrary to the philosophy that is expected and required within WE. You should be using a MaskManager and adding it to WEManager, or an extent itself (not a world) to perform anything to do with restrictions. The "world" is basically just a wrapper for the very basic world in NMS, even in upstream worldedit, and thus there cannot be a guarantee that overriding some methods in a world will have any effect on the outcome of an edit.
I hope this makes sense, it was written at midnight.
@dordsor21 Thank you for the explanation, but maybe I should explain my use case a bit more. Blocking any input into the world is only one part of the task I am trying to accomplish.
The original use case is to simulate a possible Operation applied to a world. Since I need an edit session for this anyway, it would be most practical to use the session anyway. This would also allow it to be used with everything FAWE offers in terms of brush implementations for example. So the goal is to perform dry runs of Operations and capturing the changes which would be applied. Blocking the input itself is not the goal but a side effect.
Setting an own extend for a brush is not possible for example since the build method only accepts an EditSession which is used as the extent as well. I understand that fawe takes shortcuts to accomplish its performance but i am wondering if it is even possible to satisfy this use case with the way fawe works currently.
Yeah so you really shouldn't be using a world here, and need to create a custom extent, the current process for which is to listen to EditSessionEvent and then set the extent you want to use to that, normally wrapping the extent provided initially by the event. There is currently not a way to insert your own extent when the editsession is directly made via the API, however, there's no reason an EditSessionEvent listener couldn't be made to only act when required.
We tested against to normal worldedit. There works the solution. Is issue is only present on fawe
Yeah ultimately this behaviour should be going into a processor. Setting blocks via an extent block-by-block is much slower than using processors. Examples can be seen at https://github.com/IntellectualSites/FastAsyncWorldEdit/blob/main/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java#L126-L167 and https://github.com/IntellectualSites/FastAsyncWorldEdit/blob/main/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java#L105-L151