1010import com .sk89q .worldedit .math .BlockVector3 ;
1111import com .sk89q .worldedit .regions .CuboidRegion ;
1212import com .sk89q .worldedit .session .ClipboardHolder ;
13+ import org .bukkit .Bukkit ;
1314import org .bukkit .Location ;
1415import org .bukkit .World ;
1516
1920 */
2021public final class ArenaDuplicator {
2122
23+ /**
24+ * FAWE corrupts chunk data when multiple EditSessions edit a world concurrently. Batch duplicate creation
25+ * spawns one async task per duplicate, so all FAWE work is serialized through this lock to prevent the
26+ * "random blocks" corruption.
27+ */
28+ private static final Object FAWE_LOCK = new Object ();
29+
2230 public static boolean isAvailable () {
23- return org . bukkit . Bukkit .getPluginManager ().getPlugin ("FastAsyncWorldEdit" ) != null ;
31+ return Bukkit .getPluginManager ().getPlugin ("FastAsyncWorldEdit" ) != null ;
2432 }
2533
2634 public static void copyPaste (World sourceWorld , Location min , Location max , World targetWorld , int tx , int ty , int tz ) {
@@ -30,18 +38,20 @@ public static void copyPaste(World sourceWorld, Location min, Location max, Worl
3038 BlockArrayClipboard clipboard = new BlockArrayClipboard (region );
3139 clipboard .setOrigin (region .getMinimumPoint ());
3240
33- try (EditSession source = WorldEdit .getInstance ().newEditSession (BukkitAdapter .adapt (sourceWorld ))) {
34- ForwardExtentCopy copy = new ForwardExtentCopy (source , region , clipboard , region .getMinimumPoint ());
35- copy .setCopyingEntities (false );
36- Operations .complete (copy );
37- }
41+ synchronized (FAWE_LOCK ) {
42+ try (EditSession source = WorldEdit .getInstance ().newEditSession (BukkitAdapter .adapt (sourceWorld ))) {
43+ ForwardExtentCopy copy = new ForwardExtentCopy (source , region , clipboard , region .getMinimumPoint ());
44+ copy .setCopyingEntities (false );
45+ Operations .complete (copy );
46+ }
3847
39- try (EditSession target = WorldEdit .getInstance ().newEditSession (BukkitAdapter .adapt (targetWorld ))) {
40- Operations .complete (new ClipboardHolder (clipboard )
41- .createPaste (target )
42- .to (BlockVector3 .at (tx , ty , tz ))
43- .ignoreAirBlocks (false )
44- .build ());
48+ try (EditSession target = WorldEdit .getInstance ().newEditSession (BukkitAdapter .adapt (targetWorld ))) {
49+ Operations .complete (new ClipboardHolder (clipboard )
50+ .createPaste (target )
51+ .to (BlockVector3 .at (tx , ty , tz ))
52+ .ignoreAirBlocks (false )
53+ .build ());
54+ }
4555 }
4656 }
4757
@@ -55,10 +65,12 @@ public static Object capture(World world, Location min, Location max) {
5565 BlockArrayClipboard clipboard = new BlockArrayClipboard (region );
5666 clipboard .setOrigin (region .getMinimumPoint ());
5767
58- try (EditSession source = WorldEdit .getInstance ().newEditSession (BukkitAdapter .adapt (world ))) {
59- ForwardExtentCopy copy = new ForwardExtentCopy (source , region , clipboard , region .getMinimumPoint ());
60- copy .setCopyingEntities (false );
61- Operations .complete (copy );
68+ synchronized (FAWE_LOCK ) {
69+ try (EditSession source = WorldEdit .getInstance ().newEditSession (BukkitAdapter .adapt (world ))) {
70+ ForwardExtentCopy copy = new ForwardExtentCopy (source , region , clipboard , region .getMinimumPoint ());
71+ copy .setCopyingEntities (false );
72+ Operations .complete (copy );
73+ }
6274 }
6375 return clipboard ;
6476 }
@@ -68,12 +80,14 @@ public static Object capture(World world, Location min, Location max) {
6880 */
6981 public static void restore (World world , Object clipboard ) {
7082 Clipboard clip = (Clipboard ) clipboard ;
71- try (EditSession target = WorldEdit .getInstance ().newEditSession (BukkitAdapter .adapt (world ))) {
72- Operations .complete (new ClipboardHolder (clip )
73- .createPaste (target )
74- .to (clip .getOrigin ())
75- .ignoreAirBlocks (false )
76- .build ());
83+ synchronized (FAWE_LOCK ) {
84+ try (EditSession target = WorldEdit .getInstance ().newEditSession (BukkitAdapter .adapt (world ))) {
85+ Operations .complete (new ClipboardHolder (clip )
86+ .createPaste (target )
87+ .to (clip .getOrigin ())
88+ .ignoreAirBlocks (false )
89+ .build ());
90+ }
7791 }
7892 }
7993}
0 commit comments