From acbe2f476a8e908092effc59828c3550392735ef Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:48:19 +0000 Subject: [PATCH 01/59] Update dependency paperweight-userdev to v1.21.1-R0.1-20240818.224341-32 (#2885) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts index 253af67e6..a589c6b09 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.1-R0.1-SNAPSHOT/ - the().paperDevBundle("1.21.1-R0.1-20240811.223934-9") + the().paperDevBundle("1.21.1-R0.1-20240818.224341-32") compileOnly(libs.paperlib) } From 543f3c4229e21d0a7a56be6a2f23d6a39f88d6ee Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:48:37 +0000 Subject: [PATCH 02/59] Update plugin xyz.jpenilla.run-paper to v2.3.1 (#2886) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 12ad4a353..5c8ce8016 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ import xyz.jpenilla.runpaper.task.RunServer plugins { id("io.github.gradle-nexus.publish-plugin") version "2.0.0" - id("xyz.jpenilla.run-paper") version "2.3.0" + id("xyz.jpenilla.run-paper") version "2.3.1" } if (!File("$rootDir/.git").exists()) { From 886264e0d97ef01b32f6d6ac74363e3c20d27b70 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 03:54:59 +0000 Subject: [PATCH 03/59] Update dependency commons-cli:commons-cli to v1.9.0 (#2887) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 12f0abf24..927abab42 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -35,7 +35,7 @@ jlibnoise = "1.0.0" jchronic = "0.2.4a" lz4-java = "1.8.0" lz4-stream = "1.0.0" -commons-cli = "1.8.0" +commons-cli = "1.9.0" paperlib = "1.0.8" paster = "1.1.6" vault = "1.7.1" From a64e09a7b0aca2e32a496b3c500f568dce4ae0dc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 03:59:38 +0000 Subject: [PATCH 04/59] Update dependency gradle to v8.10 (#2888) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 09523c0e5..9355b4155 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 1a674723e9cd9c8607b437b7b3c48397f1f07291 Mon Sep 17 00:00:00 2001 From: Alexander Brandes Date: Thu, 22 Aug 2024 18:31:28 +0200 Subject: [PATCH 05/59] Update wrapper Signed-off-by: Alexander Brandes --- gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43504 bytes gradlew | 7 +++++-- gradlew.bat | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..2c3521197d7c4586c843d1d3e9090525f1898cde 100644 GIT binary patch delta 8703 zcmYLtRag{&)-BQ@Dc#cDDP2Q%r*wBHJ*0FE-92)X$3_b$L+F2Fa28UVeg>}yRjC}^a^+(Cdu_FTlV;w_x7ig{yd(NYi_;SHXEq`|Qa`qPMf1B~v#%<*D zn+KWJfX#=$FMopqZ>Cv7|0WiA^M(L@tZ=_Hi z*{?)#Cn^{TIzYD|H>J3dyXQCNy8f@~OAUfR*Y@C6r=~KMZ{X}q`t@Er8NRiCUcR=?Y+RMv`o0i{krhWT6XgmUt!&X=e_Q2=u@F=PXKpr9-FL@0 zfKigQcGHyPn{3vStLFk=`h@+Lh1XBNC-_nwNU{ytxZF$o}oyVfHMj|ZHWmEmZeNIlO5eLco<=RI&3=fYK*=kmv*75aqE~&GtAp(VJ z`VN#&v2&}|)s~*yQ)-V2@RmCG8lz5Ysu&I_N*G5njY`<@HOc*Bj)ZwC%2|2O<%W;M z+T{{_bHLh~n(rM|8SpGi8Whep9(cURNRVfCBQQ2VG<6*L$CkvquqJ~9WZ~!<6-EZ&L(TN zpSEGXrDiZNz)`CzG>5&_bxzBlXBVs|RTTQi5GX6s5^)a3{6l)Wzpnc|Cc~(5mO)6; z6gVO2Zf)srRQ&BSeg0)P2en#<)X30qXB{sujc3Ppm4*)}zOa)@YZ<%1oV9K%+(VzJ zk(|p>q-$v>lImtsB)`Mm;Z0LaU;4T1BX!wbnu-PSlH1%`)jZZJ(uvbmM^is*r=Y{B zI?(l;2n)Nx!goxrWfUnZ?y5$=*mVU$Lpc_vS2UyW>tD%i&YYXvcr1v7hL2zWkHf42 z_8q$Gvl>%468i#uV`RoLgrO+R1>xP8I^7~&3(=c-Z-#I`VDnL`6stnsRlYL zJNiI`4J_0fppF<(Ot3o2w?UT*8QQrk1{#n;FW@4M7kR}oW-}k6KNQaGPTs=$5{Oz} zUj0qo@;PTg#5moUF`+?5qBZ)<%-$qw(Z?_amW*X}KW4j*FmblWo@SiU16V>;nm`Eg zE0MjvGKN_eA%R0X&RDT!hSVkLbF`BFf;{8Nym#1?#5Fb?bAHY(?me2tww}5K9AV9y+T7YaqaVx8n{d=K`dxS|=))*KJn(~8u@^J% zj;8EM+=Dq^`HL~VPag9poTmeP$E`npJFh^|=}Mxs2El)bOyoimzw8(RQle(f$n#*v zzzG@VOO(xXiG8d?gcsp-Trn-36}+S^w$U(IaP`-5*OrmjB%Ozzd;jfaeRHAzc_#?- z`0&PVZANQIcb1sS_JNA2TFyN$*yFSvmZbqrRhfME3(PJ62u%KDeJ$ZeLYuiQMC2Sc z35+Vxg^@gSR6flp>mS|$p&IS7#fL@n20YbNE9(fH;n%C{w?Y0=N5?3GnQLIJLu{lm zV6h@UDB+23dQoS>>)p`xYe^IvcXD*6nDsR;xo?1aNTCMdbZ{uyF^zMyloFDiS~P7W>WuaH2+`xp0`!d_@>Fn<2GMt z&UTBc5QlWv1)K5CoShN@|0y1M?_^8$Y*U(9VrroVq6NwAJe zxxiTWHnD#cN0kEds(wN8YGEjK&5%|1pjwMH*81r^aXR*$qf~WiD2%J^=PHDUl|=+f zkB=@_7{K$Fo0%-WmFN_pyXBxl^+lLG+m8Bk1OxtFU}$fQU8gTYCK2hOC0sVEPCb5S z4jI07>MWhA%cA{R2M7O_ltorFkJ-BbmPc`{g&Keq!IvDeg8s^PI3a^FcF z@gZ2SB8$BPfenkFc*x#6&Z;7A5#mOR5qtgE}hjZ)b!MkOQ zEqmM3s>cI_v>MzM<2>U*eHoC69t`W`^9QBU^F$ z;nU4%0$)$ILukM6$6U+Xts8FhOFb|>J-*fOLsqVfB=vC0v2U&q8kYy~x@xKXS*b6i zy=HxwsDz%)!*T5Bj3DY1r`#@Tc%LKv`?V|g6Qv~iAnrqS+48TfuhmM)V_$F8#CJ1j4;L}TBZM~PX!88IT+lSza{BY#ER3TpyMqi# z#{nTi!IsLYt9cH?*y^bxWw4djrd!#)YaG3|3>|^1mzTuXW6SV4+X8sA2dUWcjH)a3 z&rXUMHbOO?Vcdf3H<_T-=DB0M4wsB;EL3lx?|T(}@)`*C5m`H%le54I{bfg7GHqYB z9p+30u+QXMt4z&iG%LSOk1uw7KqC2}ogMEFzc{;5x`hU(rh0%SvFCBQe}M#RSWJv;`KM zf7D&z0a)3285{R$ZW%+I@JFa^oZN)vx77y_;@p0(-gz6HEE!w&b}>0b)mqz-(lfh4 zGt}~Hl@{P63b#dc`trFkguB}6Flu!S;w7lp_>yt|3U=c|@>N~mMK_t#LO{n;_wp%E zQUm=z6?JMkuQHJ!1JV$gq)q)zeBg)g7yCrP=3ZA|wt9%_l#yPjsS#C7qngav8etSX+s?JJ1eX-n-%WvP!IH1%o9j!QH zeP<8aW}@S2w|qQ`=YNC}+hN+lxv-Wh1lMh?Y;LbIHDZqVvW^r;^i1O<9e z%)ukq=r=Sd{AKp;kj?YUpRcCr*6)<@Mnp-cx{rPayiJ0!7Jng}27Xl93WgthgVEn2 zQlvj!%Q#V#j#gRWx7((Y>;cC;AVbPoX*mhbqK*QnDQQ?qH+Q*$u6_2QISr!Fn;B-F@!E+`S9?+Jr zt`)cc(ZJ$9q^rFohZJoRbP&X3)sw9CLh#-?;TD}!i>`a;FkY6(1N8U-T;F#dGE&VI zm<*Tn>EGW(TioP@hqBg zn6nEolK5(}I*c;XjG!hcI0R=WPzT)auX-g4Znr;P`GfMa*!!KLiiTqOE*STX4C(PD z&}1K|kY#>~>sx6I0;0mUn8)=lV?o#Bcn3tn|M*AQ$FscYD$0H(UKzC0R588Mi}sFl z@hG4h^*;_;PVW#KW=?>N)4?&PJF&EO(X?BKOT)OCi+Iw)B$^uE)H>KQZ54R8_2z2_ z%d-F7nY_WQiSB5vWd0+>^;G^j{1A%-B359C(Eji{4oLT9wJ~80H`6oKa&{G- z)2n-~d8S0PIkTW_*Cu~nwVlE&Zd{?7QbsGKmwETa=m*RG>g??WkZ|_WH7q@ zfaxzTsOY2B3!Fu;rBIJ~aW^yqn{V;~4LS$xA zGHP@f>X^FPnSOxEbrnEOd*W7{c(c`b;RlOEQ*x!*Ek<^p*C#8L=Ty^S&hg zaV)g8<@!3p6(@zW$n7O8H$Zej+%gf^)WYc$WT{zp<8hmn!PR&#MMOLm^hcL2;$o=Q zXJ=9_0vO)ZpNxPjYs$nukEGK2bbL%kc2|o|zxYMqK8F?$YtXk9Owx&^tf`VvCCgUz zLNmDWtociY`(}KqT~qnVUkflu#9iVqXw7Qi7}YT@{K2Uk(Wx7Q-L}u^h+M(81;I*J ze^vW&-D&=aOQq0lF5nLd)OxY&duq#IdK?-r7En0MnL~W51UXJQFVVTgSl#85=q$+| zHI%I(T3G8ci9Ubq4(snkbQ*L&ksLCnX_I(xa1`&(Bp)|fW$kFot17I)jyIi06dDTTiI%gNR z8i*FpB0y0 zjzWln{UG1qk!{DEE5?0R5jsNkJ(IbGMjgeeNL4I9;cP&>qm%q7cHT}@l0v;TrsuY0 zUg;Z53O-rR*W!{Q*Gp26h`zJ^p&FmF0!EEt@R3aT4YFR0&uI%ko6U0jzEYk_xScP@ zyk%nw`+Ic4)gm4xvCS$)y;^)B9^}O0wYFEPas)!=ijoBCbF0DbVMP z`QI7N8;88x{*g=51AfHx+*hoW3hK(?kr(xVtKE&F-%Tb}Iz1Z8FW>usLnoCwr$iWv ztOVMNMV27l*fFE29x}veeYCJ&TUVuxsd`hV-8*SxX@UD6au5NDhCQ4Qs{{CJQHE#4 z#bg6dIGO2oUZQVY0iL1(Q>%-5)<7rhnenUjOV53*9Qq?aU$exS6>;BJqz2|#{We_| zX;Nsg$KS<+`*5=WA?idE6G~kF9oQPSSAs#Mh-|)@kh#pPCgp&?&=H@Xfnz`5G2(95 z`Gx2RfBV~`&Eyq2S9m1}T~LI6q*#xC^o*EeZ#`}Uw)@RD>~<_Kvgt2?bRbO&H3&h- zjB&3bBuWs|YZSkmcZvX|GJ5u7#PAF$wj0ULv;~$7a?_R%e%ST{al;=nqj-<0pZiEgNznHM;TVjCy5E#4f?hudTr0W8)a6o;H; zhnh6iNyI^F-l_Jz$F`!KZFTG$yWdioL=AhImGr!$AJihd{j(YwqVmqxMKlqFj<_Hlj@~4nmrd~&6#f~9>r2_e-^nca(nucjf z;(VFfBrd0?k--U9L*iey5GTc|Msnn6prtF*!5AW3_BZ9KRO2(q7mmJZ5kz-yms`04e; z=uvr2o^{lVBnAkB_~7b7?1#rDUh4>LI$CH1&QdEFN4J%Bz6I$1lFZjDz?dGjmNYlD zDt}f;+xn-iHYk~V-7Fx!EkS``+w`-f&Ow>**}c5I*^1tpFdJk>vG23PKw}FrW4J#x zBm1zcp^){Bf}M|l+0UjvJXRjP3~!#`I%q*E=>?HLZ>AvB5$;cqwSf_*jzEmxxscH; zcl>V3s>*IpK`Kz1vP#APs#|tV9~#yMnCm&FOllccilcNmAwFdaaY7GKg&(AKG3KFj zk@%9hYvfMO;Vvo#%8&H_OO~XHlwKd()gD36!_;o z*7pl*o>x9fbe?jaGUO25ZZ@#qqn@|$B+q49TvTQnasc$oy`i~*o}Ka*>Wg4csQOZR z|Fs_6-04vj-Dl|B2y{&mf!JlPJBf3qG~lY=a*I7SBno8rLRdid7*Kl@sG|JLCt60# zqMJ^1u^Gsb&pBPXh8m1@4;)}mx}m%P6V8$1oK?|tAk5V6yyd@Ez}AlRPGcz_b!c;; z%(uLm1Cp=NT(4Hcbk;m`oSeW5&c^lybx8+nAn&fT(!HOi@^&l1lDci*?L#*J7-u}} z%`-*V&`F1;4fWsvcHOlZF#SD&j+I-P(Mu$L;|2IjK*aGG3QXmN$e}7IIRko8{`0h9 z7JC2vi2Nm>g`D;QeN@^AhC0hKnvL(>GUqs|X8UD1r3iUc+-R4$=!U!y+?p6rHD@TL zI!&;6+LK_E*REZ2V`IeFP;qyS*&-EOu)3%3Q2Hw19hpM$3>v!!YABs?mG44{L=@rjD%X-%$ajTW7%t_$7to%9d3 z8>lk z?_e}(m&>emlIx3%7{ER?KOVXi>MG_)cDK}v3skwd%Vqn0WaKa1;e=bK$~Jy}p#~`B zGk-XGN9v)YX)K2FM{HNY-{mloSX|a?> z8Om9viiwL|vbVF~j%~hr;|1wlC0`PUGXdK12w;5Wubw}miQZ)nUguh?7asm90n>q= z;+x?3haT5#62bg^_?VozZ-=|h2NbG%+-pJ?CY(wdMiJ6!0ma2x{R{!ys=%in;;5@v z{-rpytg){PNbCGP4Ig>=nJV#^ie|N68J4D;C<1=$6&boh&ol~#A?F-{9sBL*1rlZshXm~6EvG!X9S zD5O{ZC{EEpHvmD5K}ck+3$E~{xrrg*ITiA}@ZCoIm`%kVqaX$|#ddV$bxA{jux^uRHkH)o6#}fT6XE|2BzU zJiNOAqcxdcQdrD=U7OVqer@p>30l|ke$8h;Mny-+PP&OM&AN z9)!bENg5Mr2g+GDIMyzQpS1RHE6ow;O*ye;(Qqej%JC?!D`u;<;Y}1qi5cL&jm6d9 za{plRJ0i|4?Q%(t)l_6f8An9e2<)bL3eULUVdWanGSP9mm?PqFbyOeeSs9{qLEO-) zTeH*<$kRyrHPr*li6p+K!HUCf$OQIqwIw^R#mTN>@bm^E=H=Ger_E=ztfGV9xTgh=}Hep!i97A;IMEC9nb5DBA5J#a8H_Daq~ z6^lZ=VT)7=y}H3=gm5&j!Q79#e%J>w(L?xBcj_RNj44r*6^~nCZZYtCrLG#Njm$$E z7wP?E?@mdLN~xyWosgwkCot8bEY-rUJLDo7gukwm@;TjXeQ>fr(wKP%7LnH4Xsv?o zUh6ta5qPx8a5)WO4 zK37@GE@?tG{!2_CGeq}M8VW(gU6QXSfadNDhZEZ}W2dwm)>Y7V1G^IaRI9ugWCP#sw1tPtU|13R!nwd1;Zw8VMx4hUJECJkocrIMbJI zS9k2|`0$SD%;g_d0cmE7^MXP_;_6`APcj1yOy_NXU22taG9Z;C2=Z1|?|5c^E}dR& zRfK2Eo=Y=sHm@O1`62ciS1iKv9BX=_l7PO9VUkWS7xlqo<@OxlR*tn$_WbrR8F?ha zBQ4Y!is^AIsq-46^uh;=9B`gE#Sh+4m>o@RMZFHHi=qb7QcUrgTos$e z^4-0Z?q<7XfCP~d#*7?hwdj%LyPj2}bsdWL6HctL)@!tU$ftMmV=miEvZ2KCJXP%q zLMG&%rVu8HaaM-tn4abcSE$88EYmK|5%_29B*L9NyO|~j3m>YGXf6fQL$(7>Bm9o zjHfJ+lmYu_`+}xUa^&i81%9UGQ6t|LV45I)^+m@Lz@jEeF;?_*y>-JbK`=ZVsSEWZ z$p^SK_v(0d02AyIv$}*8m)9kjef1-%H*_daPdSXD6mpc>TW`R$h9On=Z9n>+f4swL zBz^(d9uaQ_J&hjDvEP{&6pNz-bg;A===!Ac%}bu^>0}E)wdH1nc}?W*q^J2SX_A*d zBLF@n+=flfH96zs@2RlOz&;vJPiG6In>$&{D+`DNgzPYVu8<(N&0yPt?G|>D6COM# zVd)6v$i-VtYfYi1h)pXvO}8KO#wuF=F^WJXPC+;hqpv>{Z+FZTP1w&KaPl?D)*A=( z8$S{Fh;Ww&GqSvia6|MvKJg-RpNL<6MXTl(>1}XFfziRvPaLDT1y_tjLYSGS$N;8| zZC*Hcp!~u?v~ty3&dBm`1A&kUe6@`q!#>P>ZZZgGRYhNIxFU6B>@f@YL%hOV0=9s# z?@0~aR1|d9LFoSI+li~@?g({Y0_{~~E_MycHTXz`EZmR2$J$3QVoA25j$9pe?Ub)d z`jbm8v&V0JVfY-^1mG=a`70a_tjafgi}z-8$smw7Mc`-!*6y{rB-xN1l`G3PLBGk~ z{o(KCV0HEfj*rMAiluQuIZ1tevmU@m{adQQr3xgS!e_WXw&eE?GjlS+tL0@x%Hm{1 zzUF^qF*2KAxY0$~pzVRpg9dA*)^ z7&wu-V$7+Jgb<5g;U1z*ymus?oZi7&gr!_3zEttV`=5VlLtf!e&~zv~PdspA0JCRz zZi|bO5d)>E;q)?}OADAhGgey#6(>+36XVThP%b#8%|a9B_H^)Nps1md_lVv5~OO@(*IJO@;eqE@@(y}KA- z`zj@%6q#>hIgm9}*-)n(^Xbdp8`>w~3JCC`(H{NUh8Umm{NUntE+eMg^WvSyL+ilV zff54-b59jg&r_*;*#P~ON#I=gAW99hTD;}nh_j;)B6*tMgP_gz4?=2EJZg$8IU;Ly<(TTC?^)& zj@%V!4?DU&tE=8)BX6f~x0K+w$%=M3;Fpq$VhETRlJ8LEEe;aUcG;nBe|2Gw>+h7CuJ-^gYFhQzDg(`e=!2f7t0AXrl zAx`RQ1u1+}?EkEWSb|jQN)~wOg#Ss&1oHoFBvg{Z|4#g$)mNzjKLq+8rLR(jC(QUC Ojj7^59?Sdh$^Qpp*~F>< delta 8662 zcmYM1RaBhK(uL9BL4pT&ch}$qcL*As0R|^HFD`?-26qkaNwC3nu;A|Q0Yd)oJ7=x) z_f6HatE;=#>YLq{FoYf$!na@pfNwSyI%>|UMk5`vO(z@Ao)eZR(~D#FF?U$)+q)1q z9OVG^Ib0v?R8wYfQ*1H;5Oyixqnyt6cXR#u=LM~V7_GUu}N(b}1+x^JUL#_8Xj zB*(FInWvSPGo;K=k3}p&4`*)~)p`nX#}W&EpfKCcOf^7t zPUS81ov(mXS;$9To6q84I!tlP&+Z?lkctuIZ(SHN#^=JGZe^hr^(3d*40pYsjikBWME6IFf!!+kC*TBc!T)^&aJ#z0#4?OCUbNoa}pwh=_SFfMf|x$`-5~ zP%%u%QdWp#zY6PZUR8Mz1n$f44EpTEvKLTL;yiZrPCV=XEL09@qmQV#*Uu*$#-WMN zZ?rc(7}93z4iC~XHcatJev=ey*hnEzajfb|22BpwJ4jDi;m>Av|B?TqzdRm-YT(EV zCgl${%#nvi?ayAFYV7D_s#07}v&FI43BZz@`dRogK!k7Y!y6r=fvm~=F9QP{QTj>x z#Y)*j%`OZ~;rqP0L5@qYhR`qzh^)4JtE;*faTsB;dNHyGMT+fpyz~LDaMOO?c|6FD z{DYA+kzI4`aD;Ms|~h49UAvOfhMEFip&@&Tz>3O+MpC0s>`fl!T(;ZP*;Ux zr<2S-wo(Kq&wfD_Xn7XXQJ0E4u7GcC6pqe`3$fYZ5Eq4`H67T6lex_QP>Ca##n2zx z!tc=_Ukzf{p1%zUUkEO(0r~B=o5IoP1@#0A=uP{g6WnPnX&!1Z$UWjkc^~o^y^Kkn z%zCrr^*BPjcTA58ZR}?%q7A_<=d&<*mXpFSQU%eiOR`=78@}+8*X##KFb)r^zyfOTxvA@cbo65VbwoK0lAj3x8X)U5*w3(}5 z(Qfv5jl{^hk~j-n&J;kaK;fNhy9ZBYxrKQNCY4oevotO-|7X}r{fvYN+{sCFn2(40 zvCF7f_OdX*L`GrSf0U$C+I@>%+|wQv*}n2yT&ky;-`(%#^vF79p1 z>y`59E$f7!vGT}d)g)n}%T#-Wfm-DlGU6CX`>!y8#tm-Nc}uH50tG)dab*IVrt-TTEM8!)gIILu*PG_-fbnFjRA+LLd|_U3yas12Lro%>NEeG%IwN z{FWomsT{DqMjq{7l6ZECb1Hm@GQ`h=dcyApkoJ6CpK3n83o-YJnXxT9b2%TmBfKZ* zi~%`pvZ*;(I%lJEt9Bphs+j#)ws}IaxQYV6 zWBgVu#Kna>sJe;dBQ1?AO#AHecU~3cMCVD&G})JMkbkF80a?(~1HF_wv6X!p z6uXt_8u)`+*%^c@#)K27b&Aa%m>rXOcGQg8o^OB4t0}@-WWy38&)3vXd_4_t%F1|( z{z(S)>S!9eUCFA$fQ^127DonBeq@5FF|IR7(tZ?Nrx0(^{w#a$-(fbjhN$$(fQA(~|$wMG4 z?UjfpyON`6n#lVwcKQ+#CuAQm^nmQ!sSk>=Mdxk9e@SgE(L2&v`gCXv&8ezHHn*@% zi6qeD|I%Q@gb(?CYus&VD3EE#xfELUvni89Opq-6fQmY-9Di3jxF?i#O)R4t66ekw z)OW*IN7#{_qhrb?qlVwmM@)50jEGbjTiDB;nX{}%IC~pw{ev#!1`i6@xr$mgXX>j} zqgxKRY$fi?B7|GHArqvLWu;`?pvPr!m&N=F1<@i-kzAmZ69Sqp;$)kKg7`76GVBo{ zk+r?sgl{1)i6Hg2Hj!ehsDF3tp(@n2+l%ihOc7D~`vzgx=iVU0{tQ&qaV#PgmalfG zPj_JimuEvo^1X)dGYNrTHBXwTe@2XH-bcnfpDh$i?Il9r%l$Ob2!dqEL-To>;3O>` z@8%M*(1#g3_ITfp`z4~Z7G7ZG>~F0W^byMvwzfEf*59oM*g1H)8@2zL&da+$ms$Dp zrPZ&Uq?X)yKm7{YA;mX|rMEK@;W zA-SADGLvgp+)f01=S-d$Z8XfvEZk$amHe}B(gQX-g>(Y?IA6YJfZM(lWrf);5L zEjq1_5qO6U7oPSb>3|&z>OZ13;mVT zWCZ=CeIEK~6PUv_wqjl)pXMy3_46hB?AtR7_74~bUS=I}2O2CjdFDA*{749vOj2hJ z{kYM4fd`;NHTYQ_1Rk2dc;J&F2ex^}^%0kleFbM!yhwO|J^~w*CygBbkvHnzz@a~D z|60RVTr$AEa-5Z->qEMEfau=__2RanCTKQ{XzbhD{c!e5hz&$ZvhBX0(l84W%eW17 zQ!H)JKxP$wTOyq83^qmx1Qs;VuWuxclIp!BegkNYiwyMVBay@XWlTpPCzNn>&4)f* zm&*aS?T?;6?2>T~+!=Gq4fjP1Z!)+S<xiG>XqzY@WKKMzx?0|GTS4{ z+z&e0Uysciw#Hg%)mQ3C#WQkMcm{1yt(*)y|yao2R_FRX$WPvg-*NPoj%(k*{BA8Xx&0HEqT zI0Swyc#QyEeUc)0CC}x{p+J{WN>Z|+VZWDpzW`bZ2d7^Yc4ev~9u-K&nR zl#B0^5%-V4c~)1_xrH=dGbbYf*7)D&yy-}^V|Np|>V@#GOm($1=El5zV?Z`Z__tD5 zcLUi?-0^jKbZrbEny&VD!zA0Nk3L|~Kt4z;B43v@k~ zFwNisc~D*ZROFH;!f{&~&Pof-x8VG8{gSm9-Yg$G(Q@O5!A!{iQH0j z80Rs>Ket|`cbw>z$P@Gfxp#wwu;I6vi5~7GqtE4t7$Hz zPD=W|mg%;0+r~6)dC>MJ&!T$Dxq3 zU@UK_HHc`_nI5;jh!vi9NPx*#{~{$5Azx`_VtJGT49vB_=WN`*i#{^X`xu$9P@m>Z zL|oZ5CT=Zk?SMj{^NA5E)FqA9q88h{@E96;&tVv^+;R$K`kbB_ zZneKrSN+IeIrMq;4EcH>sT2~3B zrZf-vSJfekcY4A%e2nVzK8C5~rAaP%dV2Hwl~?W87Hdo<*EnDcbZqVUb#8lz$HE@y z2DN2AQh%OcqiuWRzRE>cKd)24PCc)#@o&VCo!Rcs;5u9prhK}!->CC)H1Sn-3C7m9 zyUeD#Udh1t_OYkIMAUrGU>ccTJS0tV9tW;^-6h$HtTbon@GL1&OukJvgz>OdY)x4D zg1m6Y@-|p;nB;bZ_O>_j&{BmuW9km4a728vJV5R0nO7wt*h6sy7QOT0ny-~cWTCZ3 z9EYG^5RaAbLwJ&~d(^PAiicJJs&ECAr&C6jQcy#L{JCK&anL)GVLK?L3a zYnsS$+P>UB?(QU7EI^%#9C;R-jqb;XWX2Bx5C;Uu#n9WGE<5U=zhekru(St>|FH2$ zOG*+Tky6R9l-yVPJk7giGulOO$gS_c!DyCog5PT`Sl@P!pHarmf7Y0HRyg$X@fB7F zaQy&vnM1KZe}sHuLY5u7?_;q!>mza}J?&eLLpx2o4q8$qY+G2&Xz6P8*fnLU+g&i2}$F%6R_Vd;k)U{HBg{+uuKUAo^*FRg!#z}BajS)OnqwXd!{u>Y&aH?)z%bwu_NB9zNw+~661!> zD3%1qX2{743H1G8d~`V=W`w7xk?bWgut-gyAl*6{dW=g_lU*m?fJ>h2#0_+J3EMz_ zR9r+0j4V*k>HU`BJaGd~@*G|3Yp?~Ljpth@!_T_?{an>URYtict~N+wb}%n)^GE8eM(=NqLnn*KJnE*v(7Oo)NmKB*qk;0&FbO zkrIQs&-)ln0-j~MIt__0pLdrcBH{C(62`3GvGjR?`dtTdX#tf-2qkGbeV;Ud6Dp0& z|A6-DPgg=v*%2`L4M&p|&*;;I`=Tn1M^&oER=Gp&KHBRxu_OuFGgX;-U8F?*2>PXjb!wwMMh_*N8$?L4(RdvV#O5cUu0F|_zQ#w1zMA4* zJeRk}$V4?zPVMB=^}N7x?(P7!x6BfI%*)yaUoZS0)|$bw07XN{NygpgroPW>?VcO} z@er3&#@R2pLVwkpg$X8HJM@>FT{4^Wi&6fr#DI$5{ERpM@|+60{o2_*a7k__tIvGJ9D|NPoX@$4?i_dQPFkx0^f$=#_)-hphQ93a0|`uaufR!Nlc^AP+hFWe~(j_DCZmv;7CJ4L7tWk{b;IFDvT zchD1qB=cE)Mywg5Nw>`-k#NQhT`_X^c`s$ODVZZ-)T}vgYM3*syn41}I*rz?)`Q<* zs-^C3!9AsV-nX^0wH;GT)Y$yQC*0x3o!Bl<%>h-o$6UEG?{g1ip>njUYQ}DeIw0@qnqJyo0do(`OyE4kqE2stOFNos%!diRfe=M zeU@=V=3$1dGv5ZbX!llJ!TnRQQe6?t5o|Y&qReNOxhkEa{CE6d^UtmF@OXk<_qkc0 zc+ckH8Knc!FTjk&5FEQ}$sxj!(a4223cII&iai-nY~2`|K89YKcrYFAMo^oIh@W^; zsb{KOy?dv_D5%}zPk_7^I!C2YsrfyNBUw_ude7XDc0-+LjC0!X_moHU3wmveS@GRu zX>)G}L_j1I-_5B|b&|{ExH~;Nm!xytCyc}Ed!&Hqg;=qTK7C93f>!m3n!S5Z!m`N} zjIcDWm8ES~V2^dKuv>8@Eu)Zi{A4;qHvTW7hB6B38h%$K76BYwC3DIQ0a;2fSQvo$ z`Q?BEYF1`@I-Nr6z{@>`ty~mFC|XR`HSg(HN>&-#&eoDw-Q1g;x@Bc$@sW{Q5H&R_ z5Aici44Jq-tbGnDsu0WVM(RZ=s;CIcIq?73**v!Y^jvz7ckw*=?0=B!{I?f{68@V( z4dIgOUYbLOiQccu$X4P87wZC^IbGnB5lLfFkBzLC3hRD?q4_^%@O5G*WbD?Wug6{<|N#Fv_Zf3ST>+v_!q5!fSy#{_XVq$;k*?Ar^R&FuFM7 zKYiLaSe>Cw@`=IUMZ*U#v>o5!iZ7S|rUy2(yG+AGnauj{;z=s8KQ(CdwZ>&?Z^&Bt z+74(G;BD!N^Ke>(-wwZN5~K%P#L)59`a;zSnRa>2dCzMEz`?VaHaTC>?&o|(d6e*Z zbD!=Ua-u6T6O!gQnncZ&699BJyAg9mKXd_WO8O`N@}bx%BSq)|jgrySfnFvzOj!44 z9ci@}2V3!ag8@ZbJO;;Q5ivdTWx+TGR`?75Jcje}*ufx@%5MFUsfsi%FoEx)&uzkN zgaGFOV!s@Hw3M%pq5`)M4Nz$)~Sr9$V2rkP?B7kvI7VAcnp6iZl zOd!(TNw+UH49iHWC4!W&9;ZuB+&*@Z$}>0fx8~6J@d)fR)WG1UndfdVEeKW=HAur| z15zG-6mf`wyn&x@&?@g1ibkIMob_`x7nh7yu9M>@x~pln>!_kzsLAY#2ng0QEcj)qKGj8PdWEuYKdM!jd{ zHP6j^`1g}5=C%)LX&^kpe=)X+KR4VRNli?R2KgYlwKCN9lcw8GpWMV+1Ku)~W^jV2 zyiTv-b*?$AhvU7j9~S5+u`Ysw9&5oo0Djp8e(j25Etbx42Qa=4T~}q+PG&XdkWDNF z7bqo#7KW&%dh~ST6hbu8S=0V`{X&`kAy@8jZWZJuYE}_#b4<-^4dNUc-+%6g($yN% z5ny^;ogGh}H5+Gq3jR21rQgy@5#TCgX+(28NZ4w}dzfx-LP%uYk9LPTKABaQh1ah) z@Y(g!cLd!Mcz+e|XI@@IH9z*2=zxJ0uaJ+S(iIsk7=d>A#L<}={n`~O?UTGX{8Pda z_KhI*4jI?b{A!?~-M$xk)w0QBJb7I=EGy&o3AEB_RloU;v~F8ubD@9BbxV1c36CsTX+wzAZlvUm*;Re06D+Bq~LYg-qF4L z5kZZ80PB&4U?|hL9nIZm%jVj0;P_lXar)NSt3u8xx!K6Y0bclZ%<9fwjZ&!^;!>ug zQ}M`>k@S{BR20cyVXtKK%Qa^7?e<%VSAPGmVtGo6zc6BkO5vW5)m8_k{xT3;ocdpH zudHGT06XU@y6U!&kP8i6ubMQl>cm7=(W6P7^24Uzu4Xpwc->ib?RSHL*?!d{c-aE# zp?TrFr{4iDL3dpljl#HHbEn{~eW2Nqfksa(r-}n)lJLI%e#Bu|+1% zN&!n(nv(3^jGx?onfDcyeCC*p6)DuFn_<*62b92Pn$LH(INE{z^8y?mEvvO zZ~2I;A2qXvuj>1kk@WsECq1WbsSC!0m8n=S^t3kxAx~of0vpv{EqmAmDJ3(o;-cvf zu$33Z)C0)Y4(iBhh@)lsS|a%{;*W(@DbID^$ z|FzcJB-RFzpkBLaFLQ;EWMAW#@K(D#oYoOmcctdTV?fzM2@6U&S#+S$&zA4t<^-!V z+&#*xa)cLnfMTVE&I}o#4kxP~JT3-A)L_5O!yA2ebq?zvb0WO1D6$r9p?!L0#)Fc> z+I&?aog~FPBH}BpWfW^pyc{2i8#Io6e)^6wv}MZn&`01oq@$M@5eJ6J^IrXLI) z4C!#kh)89u5*Q@W5(rYDqBKO6&G*kPGFZfu@J}ug^7!sC(Wcv3Fbe{$Sy|{-VXTct znsP+0v}kduRs=S=x0MA$*(7xZPE-%aIt^^JG9s}8$43E~^t4=MxmMts;q2$^sj=k( z#^suR{0Wl3#9KAI<=SC6hifXuA{o02vdyq>iw%(#tv+@ov{QZBI^*^1K?Q_QQqA5n9YLRwO3a7JR+1x3#d3lZL;R1@8Z!2hnWj^_5 z^M{3wg%f15Db5Pd>tS!6Hj~n^l478ljxe@>!C;L$%rKfm#RBw^_K&i~ZyY_$BC%-L z^NdD{thVHFlnwfy(a?{%!m;U_9ic*!OPxf&5$muWz7&4VbW{PP)oE5u$uXUZU>+8R zCsZ~_*HLVnBm*^{seTAV=iN)mB0{<}C!EgE$_1RMj1kGUU?cjSWu*|zFA(ZrNE(CkY7>Mv1C)E1WjsBKAE%w}{~apwNj z0h`k)C1$TwZ<3de9+>;v6A0eZ@xHm#^7|z9`gQ3<`+lpz(1(RsgHAM@Ja+)c?;#j- zC=&5FD)m@9AX}0g9XQ_Yt4YB}aT`XxM-t>7v@BV}2^0gu0zRH%S9}!P(MBAFGyJ8F zEMdB&{eGOd$RqV77Lx>8pX^<@TdL{6^K7p$0uMTLC^n)g*yXRXMy`tqjYIZ|3b#Iv z4<)jtQU5`b{A;r2QCqIy>@!uuj^TBed3OuO1>My{GQe<^9|$4NOHTKFp{GpdFY-kC zi?uHq>lF$}<(JbQatP0*>$Aw_lygfmUyojkE=PnV)zc)7%^5BxpjkU+>ol2}WpB2hlDP(hVA;uLdu`=M_A!%RaRTd6>Mi_ozLYOEh!dfT_h0dSsnQm1bk)%K45)xLw zql&fx?ZOMBLXtUd$PRlqpo2CxNQTBb=!T|_>p&k1F})Hq&xksq>o#4b+KSs2KyxPQ z#{(qj@)9r6u2O~IqHG76@Fb~BZ4Wz_J$p_NU9-b3V$$kzjN24*sdw5spXetOuU1SR z{v}b92c>^PmvPs>BK2Ylp6&1>tnPsBA0jg0RQ{({-?^SBBm>=W>tS?_h^6%Scc)8L zgsKjSU@@6kSFX%_3%Qe{i7Z9Wg7~fM_)v?ExpM@htI{G6Db5ak(B4~4kRghRp_7zr z#Pco0_(bD$IS6l2j>%Iv^Hc)M`n-vIu;-2T+6nhW0JZxZ|NfDEh;ZnAe d|9e8rKfIInFTYPwOD9TMuEcqhmizAn{|ERF)u#Xe diff --git a/gradlew b/gradlew index 1aa94a426..f5feea6d6 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/gradlew.bat b/gradlew.bat index 7101f8e46..9b42019c7 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## From 2b1326ec7fac8c8fdc02642bcc60ba6ca348495e Mon Sep 17 00:00:00 2001 From: Alexander Brandes Date: Sun, 25 Aug 2024 11:43:56 +0200 Subject: [PATCH 06/59] Update Shadow Signed-off-by: Alexander Brandes --- buildSrc/build.gradle.kts | 2 +- buildSrc/src/main/kotlin/LibsConfig.kt | 2 +- buildSrc/src/main/kotlin/PlatformConfig.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 1ad464f55..7b227e2d8 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -23,7 +23,7 @@ val properties = Properties().also { props -> dependencies { implementation(gradleApi()) implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2") - implementation("com.github.johnrengelman:shadow:8.1.1") + implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.0") implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.2") constraints { val asmVersion = "[9.7,)" diff --git a/buildSrc/src/main/kotlin/LibsConfig.kt b/buildSrc/src/main/kotlin/LibsConfig.kt index 4bf9ffca2..0599a8567 100644 --- a/buildSrc/src/main/kotlin/LibsConfig.kt +++ b/buildSrc/src/main/kotlin/LibsConfig.kt @@ -29,7 +29,7 @@ fun Project.applyLibrariesConfiguration() { applyCommonConfiguration() apply(plugin = "java-base") apply(plugin = "maven-publish") - apply(plugin = "com.github.johnrengelman.shadow") + apply(plugin = "com.gradleup.shadow") apply(plugin = "signing") configurations { diff --git a/buildSrc/src/main/kotlin/PlatformConfig.kt b/buildSrc/src/main/kotlin/PlatformConfig.kt index 8f737e9ce..128e7f09d 100644 --- a/buildSrc/src/main/kotlin/PlatformConfig.kt +++ b/buildSrc/src/main/kotlin/PlatformConfig.kt @@ -20,7 +20,7 @@ fun Project.applyPlatformAndCoreConfiguration() { apply(plugin = "eclipse") apply(plugin = "idea") apply(plugin = "maven-publish") - apply(plugin = "com.github.johnrengelman.shadow") + apply(plugin = "com.gradleup.shadow") apply(plugin = "signing") applyCommonJavaConfiguration( From 3b4e8492765dfc7daca49b80a465335012c90dc6 Mon Sep 17 00:00:00 2001 From: Jordan Date: Sun, 25 Aug 2024 15:20:07 +0100 Subject: [PATCH 07/59] chore: warn when both history db and delete disk on logout are enabled (#2824) * chore: warn when both history db and delete disk on logout are enabled * Improve message --- .../main/java/com/fastasyncworldedit/core/Fawe.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java index 829f29da6..dac6fe9d6 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java @@ -365,6 +365,18 @@ public class Fawe { Settings.settings().QUEUE.PARALLEL_THREADS ); } + if (Settings.settings().HISTORY.DELETE_DISK_ON_LOGOUT && Settings.settings().HISTORY.USE_DATABASE) { + LOGGER.warn("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + LOGGER.warn("!!! !!!"); + LOGGER.warn("!!! Using history database whilst deleting disk history! !!!"); + LOGGER.warn("!!! You will not be able to rollback edits after a user logs !!!"); + LOGGER.warn("!!! out, recommended to disable delete-disk-on-logout if you !!!"); + LOGGER.warn("!!! you want to have full history rollback functionality. !!!"); + LOGGER.warn("!!! Disable use-database if you do not need to have rollback !!!"); + LOGGER.warn("!!! functionality and wish to disable this warning. !!!"); + LOGGER.warn("!!! !!!"); + LOGGER.warn("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); + } try { byte[] in = new byte[0]; byte[] compressed = LZ4Factory.fastestJavaInstance().fastCompressor().compress(in); From 2a70622013f1af58b8f1a5e5268cf989dbf306e0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 00:42:17 +0000 Subject: [PATCH 08/59] Update bstats to v3.0.3 (#2895) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 927abab42..f78ba625f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ towny = "0.100.3.12" plotsquared = "7.3.9" # Third party -bstats = "3.0.2" +bstats = "3.0.3" sparsebitset = "1.3" parallelgzip = "1.0.5" adventure = "4.17.0" From 75fb1cbee745ff56ca27a90736845ef0aab7d806 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 00:42:43 +0000 Subject: [PATCH 09/59] Update dependency paperweight-userdev (#2896) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts | 2 +- worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts index 1512dca87..6aac6f9d9 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.6-R0.1-SNAPSHOT/ - the().paperDevBundle("1.20.6-R0.1-20240702.153951-123") + the().paperDevBundle("1.20.6-R0.1-20240824.093908-124") compileOnly(libs.paperlib) } diff --git a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts index a589c6b09..f7ed71e29 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.1-R0.1-SNAPSHOT/ - the().paperDevBundle("1.21.1-R0.1-20240818.224341-32") + the().paperDevBundle("1.21.1-R0.1-20240825.214216-48") compileOnly(libs.paperlib) } From f5f9ae6a85dc9b3e075ee4dcc4606751c24cc9b6 Mon Sep 17 00:00:00 2001 From: Pierre Maurice Schwang Date: Thu, 29 Aug 2024 07:18:11 +0200 Subject: [PATCH 10/59] Fix: Copy-Paste-Brush with falsy mask (#2899) * fix: don't attempt to load all possible world chunks when copy pasta brush empty clipboard * chore: move check into ResizableClipboardBuilder --- .../core/extent/clipboard/ResizableClipboardBuilder.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ResizableClipboardBuilder.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ResizableClipboardBuilder.java index 05089a111..4efa4f456 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ResizableClipboardBuilder.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ResizableClipboardBuilder.java @@ -58,6 +58,9 @@ public class ResizableClipboardBuilder extends MemoryOptimizedHistory { } public Clipboard build() { + if (longSize() == 0) { + return EmptyClipboard.getInstance(); + } BlockVector3 pos1 = BlockVector3.at(minX, minY, minZ); BlockVector3 pos2 = BlockVector3.at(maxX, maxY, maxZ); CuboidRegion region = new CuboidRegion(pos1, pos2); From 6a0b006da6760d48b72ce18bda52134faad8d37d Mon Sep 17 00:00:00 2001 From: Pierre Maurice Schwang Date: Sun, 1 Sep 2024 12:25:54 +0200 Subject: [PATCH 11/59] fix: hollow on large areas fails (#2900) fix: determine BlockVector3Set by region size for recurse hollow --- .../src/main/java/com/sk89q/worldedit/EditSession.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index 926265bfb..4f987bd7e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -3611,7 +3611,8 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { } private void recurseHollow(Region region, BlockVector3 origin, Set outside, Mask mask) { - final LocalBlockVectorSet queue = new LocalBlockVectorSet(); + // FAWE start - use BlockVector3Set instead of LinkedList + final BlockVector3Set queue = BlockVector3Set.getAppropriateVectorSet(region); queue.add(origin); while (!queue.isEmpty()) { @@ -3634,6 +3635,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { } } } + // FAWE end } public int makeBiomeShape( From b4f4fc63b6556fefd2d378075bc8431b3c404dc7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 00:58:45 +0000 Subject: [PATCH 12/59] Update dependency paperweight-userdev to v1.21.1-R0.1-20240901.181116-54 (#2905) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts index f7ed71e29..cffccf99f 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.1-R0.1-SNAPSHOT/ - the().paperDevBundle("1.21.1-R0.1-20240825.214216-48") + the().paperDevBundle("1.21.1-R0.1-20240901.181116-54") compileOnly(libs.paperlib) } From a369513684ee42b779a00b88b72897eaade077aa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 00:59:03 +0000 Subject: [PATCH 13/59] Update dependency com.palmergames.bukkit.towny:towny to v0.100.3.13 (#2904) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f78ba625f..9aabeab5e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ mapmanager = "1.8.0-SNAPSHOT" griefprevention = "17.0.0" griefdefender = "2.1.0-SNAPSHOT" residence = "4.5._13.1" -towny = "0.100.3.12" +towny = "0.100.3.13" plotsquared = "7.3.9" # Third party From 378334bd752e5f3e61352dc50307fe3f4a8bb279 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Tue, 3 Sep 2024 21:39:32 +0200 Subject: [PATCH 14/59] Avoid map lookup in `isMovementBlocker` calls (#2906) --- .../adapter/impl/fawe/v1_20_R2/PaperweightBlockMaterial.java | 3 ++- .../adapter/impl/fawe/v1_20_R3/PaperweightBlockMaterial.java | 3 ++- .../adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java | 3 ++- .../adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightBlockMaterial.java index 2e1dd8279..a50489b93 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightBlockMaterial.java @@ -135,9 +135,10 @@ public class PaperweightBlockMaterial implements BlockMaterial { return block.isRandomlyTicking(blockState); } + @SuppressWarnings("deprecation") @Override public boolean isMovementBlocker() { - return craftMaterial.isSolid(); + return blockState.blocksMotion(); } @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightBlockMaterial.java index 74b1c035c..857d09aa6 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightBlockMaterial.java @@ -125,9 +125,10 @@ public class PaperweightBlockMaterial implements BlockMaterial { return block.isRandomlyTicking(blockState); } + @SuppressWarnings("deprecation") @Override public boolean isMovementBlocker() { - return craftMaterial.isSolid(); + return blockState.blocksMotion(); } @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java index 9c2292451..e80ecf3cb 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java @@ -126,9 +126,10 @@ public class PaperweightBlockMaterial implements BlockMaterial { return blockState.isRandomlyTicking(); } + @SuppressWarnings("deprecation") @Override public boolean isMovementBlocker() { - return craftMaterial.isSolid(); + return blockState.blocksMotion(); } @Override diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java index 359527396..537072538 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java @@ -126,9 +126,10 @@ public class PaperweightBlockMaterial implements BlockMaterial { return blockState.isRandomlyTicking(); } + @SuppressWarnings("deprecation") @Override public boolean isMovementBlocker() { - return craftMaterial.isSolid(); + return blockState.blocksMotion(); } @Override From 4b099d3588ba89c4872914653665774958c5af45 Mon Sep 17 00:00:00 2001 From: Pierre Maurice Schwang Date: Tue, 3 Sep 2024 23:16:00 +0200 Subject: [PATCH 15/59] fix(GriefDefender): invalidate mask on claim change (#2903) --- .../bukkit/regions/GriefDefenderFeature.java | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/GriefDefenderFeature.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/GriefDefenderFeature.java index 9ac2fd68a..f1baf3d9e 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/GriefDefenderFeature.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/GriefDefenderFeature.java @@ -3,7 +3,9 @@ package com.fastasyncworldedit.bukkit.regions; import com.fastasyncworldedit.core.regions.FaweMask; import com.griefdefender.api.GriefDefender; import com.griefdefender.api.claim.Claim; +import com.griefdefender.api.claim.ClaimManager; import com.griefdefender.api.claim.TrustTypes; +import com.griefdefender.lib.flowpowered.math.vector.Vector3i; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; @@ -17,8 +19,8 @@ public class GriefDefenderFeature extends BukkitMaskManager implements Listener private static final Logger LOGGER = LogManagerCompat.getLogger(); - public GriefDefenderFeature(final Plugin GriefDefenderPlugin) { - super(GriefDefenderPlugin.getName()); + public GriefDefenderFeature(final Plugin plugin) { + super(plugin.getName()); LOGGER.info("Plugin 'GriefDefender' found. Using it now."); } @@ -44,9 +46,14 @@ public class GriefDefenderFeature extends BukkitMaskManager implements Listener ); return new FaweMask(new CuboidRegion(pos1, pos2)) { + private final int[] bounds = new int[]{ + pos1.x(), pos1.y(), pos1.z(), + pos2.x(), pos2.y(), pos2.z() + }; + @Override public boolean isValid(com.sk89q.worldedit.entity.Player wePlayer, MaskType type) { - return isAllowed(player, claim, type); + return validateClaimAgainstCache(claim, bounds) && isAllowed(player, claim, type); } }; } @@ -54,4 +61,20 @@ public class GriefDefenderFeature extends BukkitMaskManager implements Listener return null; } + private static boolean validateClaimAgainstCache(Claim claim, int[] bounds) { + Vector3i min = claim.getLesserBoundaryCorner(); + Vector3i max = claim.getGreaterBoundaryCorner(); + if (min.getX() != bounds[0] || min.getY() != bounds[1] || min.getZ() != bounds[2]) { + return false; + } + if (max.getX() != bounds[3] || max.getY() != bounds[4] || max.getZ() != bounds[5]) { + return false; + } + final ClaimManager manager = GriefDefender.getCore().getClaimManager(claim.getWorldUniqueId()); + if (manager == null) { + return false; + } + return manager.getClaimByUUID(claim.getUniqueId()) != null; + } + } From 14446bc853c7dfc0a65f2d3047076197c83669e7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 01:47:18 +0000 Subject: [PATCH 16/59] Update plotsquared to v7.3.10 (#2908) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9aabeab5e..004644b3f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ griefprevention = "17.0.0" griefdefender = "2.1.0-SNAPSHOT" residence = "4.5._13.1" towny = "0.100.3.13" -plotsquared = "7.3.9" +plotsquared = "7.3.10" # Third party bstats = "3.0.3" From 9cf79d0e3b798ef6a6562e0e22be1345106f36f3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 03:15:54 +0000 Subject: [PATCH 17/59] Update dependency paperweight-userdev to v1.21.1-R0.1-20240910.023150-72 (#2907) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts index cffccf99f..4eb949758 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.1-R0.1-SNAPSHOT/ - the().paperDevBundle("1.21.1-R0.1-20240901.181116-54") + the().paperDevBundle("1.21.1-R0.1-20240910.023150-72") compileOnly(libs.paperlib) } From 5ac4d2fd5f0cba00b58361490bb23032b46bc393 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Tue, 10 Sep 2024 10:39:41 +0200 Subject: [PATCH 18/59] Replace usages and overrides of deprecated getSuggestions method (#2891) --- .../extension/factory/parser/mask/AdjacentMaskParser.java | 4 ++-- .../core/extension/factory/parser/mask/AngleMaskParser.java | 2 +- .../extension/factory/parser/mask/BesideMaskParser.java | 4 ++-- .../extension/factory/parser/mask/ExtremaMaskParser.java | 2 +- .../extension/factory/parser/mask/ROCAngleMaskParser.java | 2 +- .../extension/factory/parser/mask/RadiusMaskParser.java | 2 +- .../extension/factory/parser/mask/RichOffsetMaskParser.java | 4 ++-- .../extension/factory/parser/mask/SimplexMaskParser.java | 2 +- .../factory/parser/mask/SurfaceAngleMaskParser.java | 2 +- .../factory/parser/pattern/AngleColorPatternParser.java | 2 +- .../factory/parser/pattern/AverageColorPatternParser.java | 2 +- .../factory/parser/pattern/BiomePatternParser.java | 2 +- .../factory/parser/pattern/BufferedPattern2DParser.java | 4 ++-- .../factory/parser/pattern/BufferedPatternParser.java | 4 ++-- .../factory/parser/pattern/ColorPatternParser.java | 2 +- .../factory/parser/pattern/DesaturatePatternParser.java | 2 +- .../factory/parser/pattern/Linear2DPatternParser.java | 4 ++-- .../factory/parser/pattern/Linear3DPatternParser.java | 4 ++-- .../factory/parser/pattern/LinearPatternParser.java | 4 ++-- .../factory/parser/pattern/MaskedPatternParser.java | 6 +++--- .../extension/factory/parser/pattern/NoXPatternParser.java | 4 ++-- .../extension/factory/parser/pattern/NoYPatternParser.java | 4 ++-- .../extension/factory/parser/pattern/NoZPatternParser.java | 4 ++-- .../factory/parser/pattern/NoisePatternParser.java | 4 ++-- .../factory/parser/pattern/OffsetPatternParser.java | 4 ++-- .../parser/pattern/RandomFullClipboardPatternParser.java | 3 ++- .../factory/parser/pattern/RandomOffsetPatternParser.java | 4 ++-- .../factory/parser/pattern/RelativePatternParser.java | 4 ++-- .../factory/parser/pattern/SaturatePatternParser.java | 2 +- .../parser/pattern/SolidRandomOffsetPatternParser.java | 4 ++-- .../parser/pattern/SurfaceRandomOffsetPatternParser.java | 4 ++-- .../factory/parser/pattern/TypeSwapPatternParser.java | 2 +- .../factory/parser/transform/Linear3DTransformParser.java | 4 ++-- .../factory/parser/transform/LinearTransformParser.java | 4 ++-- .../factory/parser/transform/OffsetTransformParser.java | 4 ++-- .../factory/parser/transform/PatternTransformParser.java | 6 +++--- .../factory/parser/transform/RotateTransformParser.java | 4 ++-- .../factory/parser/transform/ScaleTransformParser.java | 4 ++-- .../factory/parser/transform/SpreadTransformParser.java | 4 ++-- 39 files changed, 67 insertions(+), 66 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AdjacentMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AdjacentMaskParser.java index 8fbcb4ae0..7521eb10a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AdjacentMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AdjacentMaskParser.java @@ -19,9 +19,9 @@ public class AdjacentMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream(); } else if (index == 1 || index == 2) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AngleMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AngleMaskParser.java index dfd62b9b8..ea8e36665 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AngleMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/AngleMaskParser.java @@ -22,7 +22,7 @@ public class AngleMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0 || index == 1) { return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); } else if (index > 1 && index <= 1 + flags.length) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/BesideMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/BesideMaskParser.java index 954b9f53d..fd597a216 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/BesideMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/BesideMaskParser.java @@ -18,9 +18,9 @@ public class BesideMaskParser extends RichParser { } @Override - protected Stream getSuggestions(final String argumentInput, final int index) { + protected Stream getSuggestions(final String argumentInput, final int index, ParserContext context) { if (index == 0) { - return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream(); } else if (index == 1 || index == 2) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ExtremaMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ExtremaMaskParser.java index a875ec802..6bab51981 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ExtremaMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ExtremaMaskParser.java @@ -22,7 +22,7 @@ public class ExtremaMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0 || index == 1) { return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); } else if (index > 1 && index <= 1 + flags.length) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ROCAngleMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ROCAngleMaskParser.java index dff4e8f32..00a285b95 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ROCAngleMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/ROCAngleMaskParser.java @@ -22,7 +22,7 @@ public class ROCAngleMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0 || index == 1) { return SuggestionHelper.suggestPositiveDoubles(argumentInput).flatMap(s -> Stream.of(s, s + "d")); } else if (index > 1 && index <= 1 + flags.length) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RadiusMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RadiusMaskParser.java index 8a57c73af..559b3bab3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RadiusMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RadiusMaskParser.java @@ -18,7 +18,7 @@ public class RadiusMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0 || index == 1) { return SuggestionHelper.suggestPositiveIntegers(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichOffsetMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichOffsetMaskParser.java index f6a21ef6f..47b56cb56 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichOffsetMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichOffsetMaskParser.java @@ -24,12 +24,12 @@ public class RichOffsetMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index < 3) { return SuggestionHelper.suggestPositiveIntegers(argumentInput); } if (index == 3) { - return worldEdit.getMaskFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SimplexMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SimplexMaskParser.java index 4674057b2..f1d2e6c55 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SimplexMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SimplexMaskParser.java @@ -20,7 +20,7 @@ public class SimplexMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index < 3) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SurfaceAngleMaskParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SurfaceAngleMaskParser.java index ab011f412..7a85e708b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SurfaceAngleMaskParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/SurfaceAngleMaskParser.java @@ -23,7 +23,7 @@ public class SurfaceAngleMaskParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index <= 2) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AngleColorPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AngleColorPatternParser.java index 7074fdb13..d471435e6 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AngleColorPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AngleColorPatternParser.java @@ -25,7 +25,7 @@ public class AngleColorPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index != 0) { return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AverageColorPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AverageColorPatternParser.java index 35d28382d..1fd2e8b2f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AverageColorPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/AverageColorPatternParser.java @@ -25,7 +25,7 @@ public class AverageColorPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index > 4) { return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BiomePatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BiomePatternParser.java index 0adbe2cd7..74e1b5b65 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BiomePatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BiomePatternParser.java @@ -54,7 +54,7 @@ public class BiomePatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { return BiomeType.REGISTRY.getSuggestions(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPattern2DParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPattern2DParser.java index 246e024c6..4ae760918 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPattern2DParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPattern2DParser.java @@ -26,9 +26,9 @@ public class BufferedPattern2DParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPatternParser.java index 49fd27495..3660aa902 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/BufferedPatternParser.java @@ -26,9 +26,9 @@ public class BufferedPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/ColorPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/ColorPatternParser.java index 9b424d5eb..0363b2ec5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/ColorPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/ColorPatternParser.java @@ -26,7 +26,7 @@ public class ColorPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index > 4) { return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/DesaturatePatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/DesaturatePatternParser.java index 2218f479e..d5ace9036 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/DesaturatePatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/DesaturatePatternParser.java @@ -25,7 +25,7 @@ public class DesaturatePatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear2DPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear2DPatternParser.java index 7da0b2377..3e77a6ef1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear2DPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear2DPatternParser.java @@ -28,9 +28,9 @@ public class Linear2DPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1, 2 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear3DPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear3DPatternParser.java index cd3a7d8db..7f7ffd7aa 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear3DPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/Linear3DPatternParser.java @@ -28,9 +28,9 @@ public class Linear3DPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/LinearPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/LinearPatternParser.java index 785e8261d..e0d5d3105 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/LinearPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/LinearPatternParser.java @@ -28,9 +28,9 @@ public class LinearPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/MaskedPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/MaskedPatternParser.java index 3aed039c3..92fcd6f5f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/MaskedPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/MaskedPatternParser.java @@ -25,10 +25,10 @@ public class MaskedPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getMaskFactory().getSuggestions(argumentInput).stream(); - case 1, 2 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getMaskFactory().getSuggestions(argumentInput, context).stream(); + case 1, 2 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); default -> Stream.empty(); }; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoXPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoXPatternParser.java index 8e3ac729f..915963d4c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoXPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoXPatternParser.java @@ -24,9 +24,9 @@ public class NoXPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoYPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoYPatternParser.java index 2cc00c8ad..34e3724a4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoYPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoYPatternParser.java @@ -24,9 +24,9 @@ public class NoYPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoZPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoZPatternParser.java index 927d13d0c..aaa9cf5fd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoZPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoZPatternParser.java @@ -24,9 +24,9 @@ public class NoZPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoisePatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoisePatternParser.java index 37ad97417..d91a66f44 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoisePatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/NoisePatternParser.java @@ -36,12 +36,12 @@ public abstract class NoisePatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } if (index == 1) { - return worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/OffsetPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/OffsetPatternParser.java index 6ae72c7a0..ff203208c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/OffsetPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/OffsetPatternParser.java @@ -25,9 +25,9 @@ public class OffsetPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomFullClipboardPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomFullClipboardPatternParser.java index 2af68adc8..587d8d81f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomFullClipboardPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomFullClipboardPatternParser.java @@ -4,6 +4,7 @@ import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.extension.factory.parser.RichParser; import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder; import com.fastasyncworldedit.core.function.pattern.RandomFullClipboardPattern; +import com.google.common.base.Function; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.util.SuggestionHelper; import com.sk89q.worldedit.extension.input.InputParseException; @@ -33,7 +34,7 @@ public class RandomFullClipboardPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { switch (index) { case 0: if (argumentInput.equals("#") || argumentInput.equals("#c")) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomOffsetPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomOffsetPatternParser.java index 2486ef119..6d910b0eb 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomOffsetPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RandomOffsetPatternParser.java @@ -25,9 +25,9 @@ public class RandomOffsetPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RelativePatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RelativePatternParser.java index bf56c1ddb..43c4d0fbf 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RelativePatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/RelativePatternParser.java @@ -24,9 +24,9 @@ public class RelativePatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SaturatePatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SaturatePatternParser.java index bb40f029d..e93521529 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SaturatePatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SaturatePatternParser.java @@ -25,7 +25,7 @@ public class SaturatePatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index > 3) { return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SolidRandomOffsetPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SolidRandomOffsetPatternParser.java index 618c463d6..ebc6b74b5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SolidRandomOffsetPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SolidRandomOffsetPatternParser.java @@ -25,9 +25,9 @@ public class SolidRandomOffsetPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1, 2, 3 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SurfaceRandomOffsetPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SurfaceRandomOffsetPatternParser.java index aa28b11d8..31a7060d5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SurfaceRandomOffsetPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/SurfaceRandomOffsetPatternParser.java @@ -25,9 +25,9 @@ public class SurfaceRandomOffsetPatternParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { return switch (index) { - case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + case 0 -> this.worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); case 1 -> SuggestionHelper.suggestPositiveIntegers(argumentInput); default -> Stream.empty(); }; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/TypeSwapPatternParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/TypeSwapPatternParser.java index 5bf33d3a0..1c4d25b91 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/TypeSwapPatternParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/pattern/TypeSwapPatternParser.java @@ -28,7 +28,7 @@ public class TypeSwapPatternParser extends RichParser { } @Override - public Stream getSuggestions(String argumentInput, int index) { + public Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index > 2) { return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/Linear3DTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/Linear3DTransformParser.java index 01d4868d3..ef72110c4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/Linear3DTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/Linear3DTransformParser.java @@ -23,9 +23,9 @@ public class Linear3DTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/LinearTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/LinearTransformParser.java index 026f38338..fb646b56b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/LinearTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/LinearTransformParser.java @@ -23,9 +23,9 @@ public class LinearTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/OffsetTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/OffsetTransformParser.java index 471359b78..3aeebfd45 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/OffsetTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/OffsetTransformParser.java @@ -26,11 +26,11 @@ public class OffsetTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index < 3) { return SuggestionHelper.suggestPositiveIntegers(argumentInput); } else if (index == 3) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/PatternTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/PatternTransformParser.java index cf81db4ce..6405fa5ec 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/PatternTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/PatternTransformParser.java @@ -24,11 +24,11 @@ public class PatternTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index == 0) { - return worldEdit.getPatternFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getPatternFactory().getSuggestions(argumentInput, context).stream(); } else if (index == 1) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/RotateTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/RotateTransformParser.java index 19ae8a599..c7f756efd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/RotateTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/RotateTransformParser.java @@ -25,12 +25,12 @@ public class RotateTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index < 3) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } if (index == 3) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/ScaleTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/ScaleTransformParser.java index 4bab68d0f..028c79f05 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/ScaleTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/ScaleTransformParser.java @@ -24,11 +24,11 @@ public class ScaleTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index < 3) { return SuggestionHelper.suggestPositiveDoubles(argumentInput); } else if (index == 3) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/SpreadTransformParser.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/SpreadTransformParser.java index 2f71407b2..b2ad0acbd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/SpreadTransformParser.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/transform/SpreadTransformParser.java @@ -24,11 +24,11 @@ public class SpreadTransformParser extends RichParser { } @Override - protected Stream getSuggestions(String argumentInput, int index) { + protected Stream getSuggestions(String argumentInput, int index, ParserContext context) { if (index < 3) { return SuggestionHelper.suggestPositiveIntegers(argumentInput); } else if (index == 3) { - return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream(); + return worldEdit.getTransformFactory().getSuggestions(argumentInput, context).stream(); } return Stream.empty(); } From f771b0cf907c1457c71c9d9f580563645a2526af Mon Sep 17 00:00:00 2001 From: Pierre Maurice Schwang Date: Wed, 11 Sep 2024 22:27:12 +0200 Subject: [PATCH 19/59] fix: don't process out of bound section while trimming Y sections (#2902) * fix: don't process out of bound section while trimming Y sections * fix: handle upper sections * "fix" macos tests? * cleanup imports * update test case(s), fix upper bound(?) * chore: simplify trim logic --- .../core/queue/IBatchProcessor.java | 59 ++++---- .../core/queue/IBatchProcessorTest.java | 136 ++++++++++++++++++ 2 files changed, 166 insertions(+), 29 deletions(-) create mode 100644 worldedit-core/src/test/java/com/fastasyncworldedit/core/queue/IBatchProcessorTest.java diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java index 4ba91a4f3..6b81b61f7 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java @@ -62,40 +62,41 @@ public interface IBatchProcessor { * @return false if chunk is empty of blocks */ default boolean trimY(IChunkSet set, int minY, int maxY, final boolean keepInsideRange) { - int minLayer = (minY - 1) >> 4; - int maxLayer = (maxY + 1) >> 4; + int minLayer = minY >> 4; + int maxLayer = maxY >> 4; if (keepInsideRange) { - for (int layer = set.getMinSectionPosition(); layer <= minLayer; layer++) { - if (set.hasSection(layer)) { - if (layer == minLayer) { - char[] arr = set.loadIfPresent(layer); - if (arr != null) { - int index = (minY & 15) << 8; - for (int i = 0; i < index; i++) { - arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__; - } - set.setBlocks(layer, arr); - } - } else { - set.setBlocks(layer, null); + for (int layer = set.getMinSectionPosition(); layer <= set.getMaxSectionPosition(); layer++) { + if (!set.hasSection(layer)) { + continue; + } + // wipe all data from chunk layers above or below the max / min layer + if (layer < minLayer || layer > maxLayer) { + set.setBlocks(layer, null); + continue; + } + // if chunk layer / section is fully enclosed by minY to maxY, keep as is + if (layer > minLayer && layer < maxLayer) { + continue; + } + char[] blocks = set.loadIfPresent(layer); + if (blocks == null) { + continue; + } + // When on the minimum layer (as defined by minY), remove blocks up to minY (exclusive) + if (layer == minLayer) { + int index = (minY & 15) << 8; + for (int i = 0; i < index; i++) { + blocks[i] = BlockTypesCache.ReservedIDs.__RESERVED__; } } - } - for (int layer = maxLayer; layer <= set.getMaxSectionPosition(); layer++) { - if (set.hasSection(layer)) { - if (layer == maxLayer) { - char[] arr = set.loadIfPresent(layer); - if (arr != null) { - int index = ((maxY + 1) & 15) << 8; - for (int i = index; i < arr.length; i++) { - arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__; - } - set.setBlocks(layer, arr); - } - } else { - set.setBlocks(layer, null); + // When on the maximum layer (as defined by maxY), remove blocks above maxY (exclusive) + if (layer == maxLayer) { + int index = ((maxY & 15) + 1) << 8; + for (int i = index; i < blocks.length; i++) { + blocks[i] = BlockTypesCache.ReservedIDs.__RESERVED__; } } + set.setBlocks(layer, blocks); } try { int layer = (minY - 15) >> 4; diff --git a/worldedit-core/src/test/java/com/fastasyncworldedit/core/queue/IBatchProcessorTest.java b/worldedit-core/src/test/java/com/fastasyncworldedit/core/queue/IBatchProcessorTest.java new file mode 100644 index 000000000..e28d0d236 --- /dev/null +++ b/worldedit-core/src/test/java/com/fastasyncworldedit/core/queue/IBatchProcessorTest.java @@ -0,0 +1,136 @@ +package com.fastasyncworldedit.core.queue; + +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.world.block.BlockTypesCache; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.parallel.Isolated; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.Arrays; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class IBatchProcessorTest { + + @Nested + @Isolated + class trimY { + + private static final char[] CHUNK_DATA = new char[16 * 16 * 16]; + private static final char[] SLICE_AIR = new char[16 * 16]; + private static final char[] SLICE_RESERVED = new char[16 * 16]; + private final IBatchProcessor processor = new NoopBatchProcessor(); + + static { + Arrays.fill(CHUNK_DATA, (char) BlockTypesCache.ReservedIDs.AIR); + Arrays.fill(SLICE_AIR, (char) BlockTypesCache.ReservedIDs.AIR); + Arrays.fill(SLICE_RESERVED, (char) BlockTypesCache.ReservedIDs.__RESERVED__); + } + + @ParameterizedTest + @MethodSource("provideTrimYInBoundsParameters") + void testFullChunkSelectedInBoundedRegion(int minY, int maxY, int minSection, int maxSection) { + final IChunkSet set = mock(); + + char[][] sections = new char[(320 + 64) >> 4][CHUNK_DATA.length]; + for (final char[] chars : sections) { + System.arraycopy(CHUNK_DATA, 0, chars, 0, CHUNK_DATA.length); + } + + when(set.getMinSectionPosition()).thenReturn(-64 >> 4); + when(set.getMaxSectionPosition()).thenReturn(319 >> 4); + when(set.hasSection(anyInt())).thenReturn(true); + when(set.loadIfPresent(anyInt())).thenAnswer(invocationOnMock -> sections[invocationOnMock.getArgument(0) + 4]); + doAnswer(invocationOnMock -> { + sections[invocationOnMock.getArgument(0) + 4] = invocationOnMock.getArgument(1); + return null; + }).when(set).setBlocks(anyInt(), any()); + + processor.trimY(set, minY, maxY, true); + + + for (int section = -64 >> 4; section < 320 >> 4; section++) { + int sectionIndex = section + 4; + char[] palette = sections[sectionIndex]; + if (section < minSection) { + assertNull(palette, "expected section below minimum section to be null"); + continue; + } + if (section > maxSection) { + assertNull(palette, "expected section above maximum section to be null"); + continue; + } + if (section == minSection) { + for (int slice = 0; slice < 16; slice++) { + boolean shouldContainBlocks = slice >= (minY % 16); + // If boundaries only span one section, the upper constraints have to be checked explicitly + if (section == maxSection) { + shouldContainBlocks &= slice <= (maxY % 16); + } + assertArrayEquals( + shouldContainBlocks ? SLICE_AIR : SLICE_RESERVED, + Arrays.copyOfRange(palette, slice << 8, (slice + 1) << 8), + ("[lower] slice %d (y=%d) expected to contain " + (shouldContainBlocks ? "air" : "nothing")) + .formatted(slice, ((section << 4) + slice)) + ); + } + continue; + } + if (section == maxSection) { + for (int slice = 0; slice < 16; slice++) { + boolean shouldContainBlocks = slice <= (maxY % 16); + assertArrayEquals( + shouldContainBlocks ? SLICE_AIR : SLICE_RESERVED, + Arrays.copyOfRange(palette, slice << 8, (slice + 1) << 8), + ("[upper] slice %d (y=%d) expected to contain " + (shouldContainBlocks ? "air" : "nothing")) + .formatted(slice, ((section << 4) + slice)) + ); + } + continue; + } + assertArrayEquals(CHUNK_DATA, palette, "full captured chunk @ %d should contain full data".formatted(section)); + } + + } + + /** + * Arguments explained: + * 1. minimum y coordinate (inclusive) + * 2. maximum y coordinate (inclusive) + * 3. chunk section which contains minimum y coordinate + * 4. chunk section which contains maximum y coordinate + */ + private static Stream provideTrimYInBoundsParameters() { + return Stream.of( + Arguments.of(64, 72, 4, 4), + Arguments.of(-64, 0, -4, 0), + Arguments.of(0, 128, 0, 8), + Arguments.of(16, 132, 1, 8), + Arguments.of(4, 144, 0, 9), + Arguments.of(12, 255, 0, 15), + Arguments.of(24, 103, 1, 6) + ); + } + + } + + private static final class NoopBatchProcessor implements IBatchProcessor { + + @Override + public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { + return set; + } + + @Override + public @Nullable Extent construct(final Extent child) { + return null; + } + + } + +} From a1bea11c80cad4b19d8fae519560bc1e1668a15b Mon Sep 17 00:00:00 2001 From: Pierre Maurice Schwang Date: Wed, 11 Sep 2024 22:27:21 +0200 Subject: [PATCH 20/59] fix: allow webinterface schematic format to be detected (#2901) * fix: allow webinterface schematic format to be detected * chore: address review --- .../core/util/MainUtil.java | 4 +- .../worldedit/command/SchematicCommands.java | 62 ++++++++++++------- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java index 0c323e47b..8ab673b77 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java @@ -701,7 +701,7 @@ public class MainUtil { public static File resolve(File dir, String filename, @Nullable ClipboardFormat format, boolean allowDir) { if (format != null) { - if (!filename.matches(".*\\.[\\w].*")) { + if (!filename.matches(".*\\.\\w.*")) { filename = filename + "." + format.getPrimaryFileExtension(); } return MainUtil.resolveRelative(new File(dir, filename)); @@ -712,7 +712,7 @@ public class MainUtil { return file; } } - if (filename.matches(".*\\.[\\w].*")) { + if (filename.matches(".*\\.\\w.*")) { File file = MainUtil.resolveRelative(new File(dir, filename)); if (file.exists()) { return file; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index 615702a19..1b818786a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -69,18 +69,18 @@ import org.enginehub.piston.exception.StopExecutionException; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.Closeable; +import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; import java.io.OutputStream; +import java.net.URI; +import java.net.URL; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -91,8 +91,8 @@ import java.util.Map; import java.util.Objects; import java.util.UUID; import java.util.concurrent.Callable; -import java.util.function.Consumer; import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Consumer; import java.util.function.Function; import java.util.regex.Pattern; @@ -326,13 +326,13 @@ public class SchematicCommands { //FAWE start ClipboardFormat format; - InputStream in = null; + InputStream in; // if format is set explicitly, do not look up by extension! boolean noExplicitFormat = formatName == null; if (noExplicitFormat) { formatName = "fast"; } - try { + try(final Closer closer = Closer.create()) { URI uri; if (formatName.startsWith("url:")) { String t = filename; @@ -346,11 +346,31 @@ public class SchematicCommands { } UUID uuid = UUID.fromString(filename.substring(4)); URL webUrl = new URL(Settings.settings().WEB.URL); - format = ClipboardFormats.findByAlias(formatName); + if ((format = ClipboardFormats.findByAlias(formatName)) == null) { + actor.print(Caption.of("worldedit.schematic.unknown-format", TextComponent.of(formatName))); + return; + } + // The interface requires the correct schematic extension - otherwise it can't be downloaded + // So it basically only supports .schem files (sponge v2 + v3) - or the correct extensions is specified manually + // Sadly it's not really an API endpoint but spits out the HTML source of the uploader - so no real handling + // can happen URL url = new URL(webUrl, "uploads/" + uuid + "." + format.getPrimaryFileExtension()); - ReadableByteChannel byteChannel = Channels.newChannel(url.openStream()); - in = Channels.newInputStream(byteChannel); - uri = url.toURI(); + final Path temp = Files.createTempFile("faweremoteschem", null); + final File tempFile = temp.toFile(); + // delete temporary file when we're done + closer.register((Closeable) () -> Files.deleteIfExists(temp)); + // write schematic into temporary file + try (final InputStream urlIn = new BufferedInputStream(url.openStream()); + final OutputStream tempOut = new BufferedOutputStream(new FileOutputStream(tempFile))) { + urlIn.transferTo(tempOut); + } + // No format is specified -> try or fail + if (noExplicitFormat && (format = ClipboardFormats.findByFile(tempFile)) == null) { + actor.print(Caption.of("fawe.worldedit.schematic.schematic.load-failure", TextComponent.of(filename))); + return; + } + in = new FileInputStream(tempFile); + uri = temp.toUri(); } else { File saveDir = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile(); File dir = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS ? new File(saveDir, actor.getUniqueId().toString()) : saveDir; @@ -378,7 +398,7 @@ public class SchematicCommands { } if (!noExplicitFormat) { format = ClipboardFormats.findByAlias(formatName); - } else if (filename.matches(".*\\.[\\w].*")) { + } else if (filename.matches(".*\\.\\w.*")) { format = ClipboardFormats .findByExplicitExtension(filename.substring(filename.lastIndexOf('.') + 1)); } else { @@ -412,6 +432,7 @@ public class SchematicCommands { in = new FileInputStream(file); uri = file.toURI(); } + closer.register(in); format.hold(actor, uri, in); if (randomRotate) { AffineTransform transform = new AffineTransform(); @@ -422,19 +443,18 @@ public class SchematicCommands { actor.print(Caption.of("fawe.worldedit.schematic.schematic.loaded", filename)); } catch (IllegalArgumentException e) { actor.print(Caption.of("worldedit.schematic.unknown-filename", TextComponent.of(filename))); - } catch (URISyntaxException | IOException e) { + } catch (EOFException e) { + // EOFException is extending IOException - but the IOException error is too generic. + // EOF mostly occurs when there was unexpected content in the schematic - due to the wrong reader (= version) + actor.print(Caption.of("fawe.worldedit.schematic.schematic.load-failure", + TextComponent.of(e.getMessage() != null ? e.getMessage() : "EOFException"))); // often null... + LOGGER.error("Error loading a schematic", e); + } catch (IOException e) { actor.print(Caption.of("worldedit.schematic.file-not-exist", TextComponent.of(Objects.toString(e.getMessage())))); LOGGER.warn("Failed to load a saved clipboard", e); } catch (Exception e) { actor.print(Caption.of("fawe.worldedit.schematic.schematic.load-failure", TextComponent.of(e.getMessage()))); LOGGER.error("Error loading a schematic", e); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException ignored) { - } - } } //FAWE end } From 766a5d6da247d69bca5baa9ff0697fa226dc91bd Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Wed, 11 Sep 2024 22:27:29 +0200 Subject: [PATCH 21/59] Faster undo operations (#2898) --- .../core/configuration/Settings.java | 7 + .../core/history/change/ChangePopulator.java | 65 ++++ .../history/changeset/AbstractChangeSet.java | 8 + .../changeset/AbstractDelegateChangeSet.java | 5 + .../changeset/ChangeExchangeCoordinator.java | 50 +++ .../changeset/FaweStreamChangeSet.java | 286 ++++++++++++++++++ .../core/history/changeset/NullChangeSet.java | 11 + .../function/operation/ChangeSetExecutor.java | 31 +- 8 files changed, 461 insertions(+), 2 deletions(-) create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/ChangePopulator.java create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java index 3b80dcdfa..4db469187 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java @@ -622,6 +622,13 @@ public class Settings extends Config { }) public static class EXPERIMENTAL { + @Comment({ + "Undo operation batch size", + " - The size defines the number of changes read at once.", + " - Larger numbers might reduce overhead but increase latency for edits with only few changes.", + " - 0 means undo operations are not batched."}) + public int UNDO_BATCH_SIZE = 128; + @Comment({ "[UNSAFE] Directly modify the region files. (OBSOLETE - USE ANVIL COMMANDS)", " - IMPROPER USE CAN CAUSE WORLD CORRUPTION!", diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/ChangePopulator.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/ChangePopulator.java new file mode 100644 index 000000000..6831a443c --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/ChangePopulator.java @@ -0,0 +1,65 @@ +package com.fastasyncworldedit.core.history.change; + +import com.sk89q.worldedit.history.change.Change; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @since TODO + */ +@ApiStatus.Internal +public interface ChangePopulator { + + static ChangePopulator empty() { + class Empty implements ChangePopulator { + private static final Empty EMPTY = new Empty(); + + @Override + public @NotNull C create() { + throw new UnsupportedOperationException("empty"); + } + + @Override + public @Nullable C populate(@NotNull final C change) { + return null; + } + + @Override + public @Nullable C updateOrCreate(@Nullable final Change change) { + return null; + } + + @Override + public boolean accepts(final Change change) { + return false; + } + } + return Empty.EMPTY; + } + + @SuppressWarnings("unchecked") + default @NotNull C update(@Nullable Change before) { + if (accepts(before)) { + return (C) before; + } + return create(); + } + + @NotNull + C create(); + + @Nullable + default C updateOrCreate(@Nullable Change change) { + C u = update(change); + return populate(u); + } + + @Nullable + C populate(@NotNull C change); + + @Contract("null->false") + boolean accepts(Change change); + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java index 346543a0b..84c1193eb 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java @@ -32,6 +32,7 @@ import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.ApiStatus; import java.io.IOException; import java.util.Iterator; @@ -250,6 +251,13 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { return getIterator(redo); } + /** + * {@return a coordinator to exchange sets of changes between a producer and a consumer} + * @since TODO + */ + @ApiStatus.Internal + public abstract ChangeExchangeCoordinator getCoordinatedChanges(BlockBag blockBag, int mode, boolean dir); + public abstract Iterator getIterator(boolean redo); public EditSession toEditSession(Actor actor) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractDelegateChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractDelegateChangeSet.java index a44e73013..f3f0cdae4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractDelegateChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractDelegateChangeSet.java @@ -76,6 +76,11 @@ public class AbstractDelegateChangeSet extends AbstractChangeSet { return parent.getIterator(blockBag, mode, redo); } + @Override + public ChangeExchangeCoordinator getCoordinatedChanges(final BlockBag blockBag, final int mode, final boolean dir) { + return parent.getCoordinatedChanges(blockBag, mode, dir); + } + @Override public Iterator getIterator(boolean redo) { return parent.getIterator(redo); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java new file mode 100644 index 000000000..56d47500f --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java @@ -0,0 +1,50 @@ +package com.fastasyncworldedit.core.history.changeset; + +import com.sk89q.worldedit.history.change.Change; +import org.jetbrains.annotations.ApiStatus; + +import java.util.concurrent.Exchanger; +import java.util.function.BiConsumer; + +/** + * @since TODO + */ +@ApiStatus.Internal +public class ChangeExchangeCoordinator implements AutoCloseable { + + private static final Thread.Builder.OfVirtual UNDO_VIRTUAL_THREAD_BUILDER = Thread.ofVirtual() + .name("FAWE undo", 0); + private final Exchanger exchanger; + private final BiConsumer, Change[]> runnerTask; + private boolean started = false; + private Thread runner; + + public ChangeExchangeCoordinator(BiConsumer, Change[]> runner) { + this.runnerTask = runner; + this.exchanger = new Exchanger<>(); + } + + public Change[] take(Change[] consumed) { + if (!this.started) { + this.started = true; + final int length = consumed.length; + this.runner = UNDO_VIRTUAL_THREAD_BUILDER + .start(() -> this.runnerTask.accept(this.exchanger, new Change[length])); + } + try { + return exchanger.exchange(consumed); + } catch (InterruptedException e) { + this.runner.interrupt(); + Thread.currentThread().interrupt(); + return null; + } + } + + @Override + public void close() { + if (this.runner != null) { + this.runner.interrupt(); + } + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java index e7132bf5a..211a71303 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java @@ -1,6 +1,7 @@ package com.fastasyncworldedit.core.history.changeset; import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.history.change.ChangePopulator; import com.fastasyncworldedit.core.history.change.MutableBiomeChange; import com.fastasyncworldedit.core.history.change.MutableBlockChange; import com.fastasyncworldedit.core.history.change.MutableEntityChange; @@ -20,15 +21,22 @@ import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockTypes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayDeque; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.concurrent.Exchanger; +import java.util.function.BiConsumer; /** * FAWE stream ChangeSet offering support for extended-height worlds @@ -711,6 +719,284 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { } } + @Override + public ChangeExchangeCoordinator getCoordinatedChanges(BlockBag blockBag, int mode, boolean dir) { + try { + return coordinatedChanges(blockBag, mode, dir); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private ChangeExchangeCoordinator coordinatedChanges(final BlockBag blockBag, final int mode, boolean dir) throws IOException { + close(); + var tileCreate = tileChangePopulator(getTileCreateIS(), true); + var tileRemove = tileChangePopulator(getTileRemoveIS(), false); + + var entityCreate = entityChangePopulator(getEntityCreateIS(), true); + var entityRemove = entityChangePopulator(getEntityRemoveIS(), false); + + var blockChange = blockBag != null && mode > 0 ? fullBlockChangePopulator(blockBag, mode, dir) : blockChangePopulator(dir); + + var biomeChange = biomeChangePopulator(dir); + + Queue> populators = new ArrayDeque<>(List.of( + tileCreate, + tileRemove, + entityCreate, + entityRemove, + blockChange, + biomeChange + )); + BiConsumer, Change[]> task = (exchanger, array) -> { + while (fillArray(array, populators)) { + try { + array = exchanger.exchange(array); + } catch (InterruptedException e) { + return; + } + } + }; + return new ChangeExchangeCoordinator(task); + } + + private boolean fillArray(Change[] changes, Queue> populators) { + ChangePopulator populator = populators.peek(); + if (populator == null) { + return false; + } + for (int i = 0; i < changes.length; i++) { + Change change = changes[i]; + do { + change = populator.updateOrCreate(change); + if (change == null) { + populators.remove(); + populator = populators.peek(); + if (populator == null) { + changes[i] = null; // mark end + return true; // still needs to consume the elements of the current round + } + } else { + break; + } + } while (true); + changes[i] = change; + } + return true; + } + + private static abstract class CompoundTagPopulator implements ChangePopulator { + private final NBTInputStream inputStream; + + private CompoundTagPopulator(final NBTInputStream stream) { + inputStream = stream; + } + + @Override + public @Nullable C populate(final @NotNull C change) { + try { + write(change, (CompoundTag) inputStream.readTag()); + return change; + } catch (Exception ignored) { + } + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + protected abstract void write(C change, CompoundTag tag); + } + + private ChangePopulator tileChangePopulator(NBTInputStream is, boolean create) { + if (is == null) { + return ChangePopulator.empty(); + } + class Populator extends CompoundTagPopulator { + + private Populator() { + super(is); + } + + @Override + public @NotNull MutableTileChange create() { + return new MutableTileChange(null, create); + } + + @Override + protected void write(final MutableTileChange change, final CompoundTag tag) { + change.tag = tag; + } + + @Override + public boolean accepts(final Change change) { + return change instanceof MutableTileChange; + } + + } + return new Populator(); + } + private ChangePopulator entityChangePopulator(NBTInputStream is, boolean create) { + if (is == null) { + return ChangePopulator.empty(); + } + class Populator extends CompoundTagPopulator { + + private Populator() { + super(is); + } + + @Override + public @NotNull MutableEntityChange create() { + return new MutableEntityChange(null, create); + } + + @Override + protected void write(final MutableEntityChange change, final CompoundTag tag) { + change.tag = tag; + } + + @Override + public boolean accepts(final Change change) { + return change instanceof MutableTileChange; + } + + } + return new Populator(); + } + + private ChangePopulator fullBlockChangePopulator(BlockBag blockBag, int mode, boolean dir) throws + IOException { + final FaweInputStream is = getBlockIS(); + if (is == null) { + return ChangePopulator.empty(); + } + class Populator implements ChangePopulator { + + @Override + public @NotNull MutableFullBlockChange create() { + return new MutableFullBlockChange(blockBag, mode, dir); + } + + @Override + public @Nullable MutableFullBlockChange populate(@NotNull final MutableFullBlockChange change) { + try { + change.x = posDel.readX(is) + originX; + change.y = posDel.readY(is); + change.z = posDel.readZ(is) + originZ; + idDel.readCombined(is, change); + return change; + } catch (EOFException ignored) { + } catch (Exception e) { + e.printStackTrace(); + } + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public boolean accepts(final Change change) { + return change instanceof MutableFullBlockChange; + } + + } + return new Populator(); + + } + + private ChangePopulator blockChangePopulator(boolean dir) throws IOException { + final FaweInputStream is = getBlockIS(); + if (is == null) { + return ChangePopulator.empty(); + } + class Populator implements ChangePopulator { + + @Override + public @NotNull MutableBlockChange create() { + return new MutableBlockChange(0, 0, 0, BlockTypes.AIR.getInternalId()); + } + + @Override + public @Nullable MutableBlockChange populate(@NotNull final MutableBlockChange change) { + try { + change.x = posDel.readX(is) + originX; + change.y = posDel.readY(is); + change.z = posDel.readZ(is) + originZ; + idDel.readCombined(is, change, dir); + return change; + } catch (EOFException ignored) { + } catch (Exception e) { + e.printStackTrace(); + } + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public boolean accepts(final Change change) { + return change instanceof MutableBlockChange; + } + + } + return new Populator(); + } + + private ChangePopulator biomeChangePopulator(boolean dir) throws IOException { + final FaweInputStream is = getBiomeIS(); + if (is == null) { + return ChangePopulator.empty(); + } + class Populator implements ChangePopulator { + + @Override + public @NotNull MutableBiomeChange create() { + return new MutableBiomeChange(); + } + + @Override + public @Nullable MutableBiomeChange populate(@NotNull final MutableBiomeChange change) { + try { + int int1 = is.read(); + if (int1 != -1) { + int x = ((int1 << 24) + (is.read() << 16) + (is.read() << 8) + is.read()) << 2; + int z = ((is.read() << 24) + (is.read() << 16) + (is.read() << 8) + is.read()) << 2; + int y = (is.read() - 128) << 2; + int from = is.readVarInt(); + int to = is.readVarInt(); + change.setBiome(x, y, z, from, to); + return change; + } + } catch (EOFException ignored) { + } catch (Exception e) { + e.printStackTrace(); + } + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public boolean accepts(final Change change) { + return change instanceof MutableBiomeChange; + } + + } + return new Populator(); + } + @Override public Iterator getIterator(final boolean dir) { try { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/NullChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/NullChangeSet.java index dd4fddf1a..2a60b3913 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/NullChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/NullChangeSet.java @@ -54,6 +54,17 @@ public class NullChangeSet extends AbstractChangeSet { return getIterator(redo); } + @Override + public ChangeExchangeCoordinator getCoordinatedChanges(final BlockBag blockBag, final int mode, final boolean dir) { + return new ChangeExchangeCoordinator(((exchanger, changes) -> { + try { + exchanger.exchange(null); + } catch (InterruptedException ignored) { + Thread.currentThread().interrupt(); + } + })); + } + @Override public final Iterator getIterator(boolean undo) { return Collections.emptyIterator(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java index 12359fdee..ea52bf335 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/operation/ChangeSetExecutor.java @@ -19,7 +19,9 @@ package com.sk89q.worldedit.function.operation; +import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet; +import com.fastasyncworldedit.core.history.changeset.ChangeExchangeCoordinator; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.history.UndoContext; @@ -56,6 +58,7 @@ public class ChangeSetExecutor implements Operation { //FAWE end private final Iterator iterator; + private final ChangeExchangeCoordinator changeExchangeCoordinator; private final Type type; private final UndoContext context; @@ -74,18 +77,42 @@ public class ChangeSetExecutor implements Operation { this.type = type; this.context = context; - if (changeSet instanceof AbstractChangeSet) { - iterator = ((AbstractChangeSet) changeSet).getIterator(blockBag, inventory, type == Type.REDO); + if (changeSet instanceof AbstractChangeSet abstractChangeSet) { + if (Settings.settings().EXPERIMENTAL.UNDO_BATCH_SIZE > 0) { + this.changeExchangeCoordinator = abstractChangeSet.getCoordinatedChanges(blockBag, inventory, type == Type.REDO); + this.iterator = null; + } else { + this.iterator = abstractChangeSet.getIterator(blockBag, inventory, type == Type.REDO); + this.changeExchangeCoordinator = null; + } } else if (type == Type.UNDO) { iterator = changeSet.backwardIterator(); + this.changeExchangeCoordinator = null; } else { iterator = changeSet.forwardIterator(); + this.changeExchangeCoordinator = null; } } //FAWE end @Override public Operation resume(RunContext run) throws WorldEditException { + // FAWE start - ChangeExchangeCoordinator + if (this.changeExchangeCoordinator != null) { + try (this.changeExchangeCoordinator) { + Change[] changes = new Change[Settings.settings().EXPERIMENTAL.UNDO_BATCH_SIZE]; + while ((changes = this.changeExchangeCoordinator.take(changes)) != null) { + for (final Change change : changes) { + if (change == null) { + return null; // end + } + type.perform(change, context); + } + } + return null; + } + } + // FAWE end while (iterator.hasNext()) { Change change = iterator.next(); //FAWE start - types > individual history step From 19370a354959bac707a5bf122e7646dccb619b39 Mon Sep 17 00:00:00 2001 From: Jordan Date: Sat, 14 Sep 2024 09:47:07 +0100 Subject: [PATCH 22/59] fix: account for spigot having private PalettedContainer#get(int) (#2910) --- .../fawe/v1_20_R2/PaperweightGetBlocks_Copy.java | 15 +++++++++++++-- .../fawe/v1_20_R2/PaperweightPlatformAdapter.java | 9 +++++++++ .../fawe/v1_20_R3/PaperweightGetBlocks_Copy.java | 15 +++++++++++++-- .../fawe/v1_20_R3/PaperweightPlatformAdapter.java | 9 +++++++++ .../fawe/v1_20_R4/PaperweightGetBlocks_Copy.java | 15 +++++++++++++-- .../fawe/v1_20_R4/PaperweightPlatformAdapter.java | 9 +++++++++ .../fawe/v1_21_R1/PaperweightGetBlocks_Copy.java | 15 +++++++++++++-- .../fawe/v1_21_R1/PaperweightPlatformAdapter.java | 9 +++++++++ 8 files changed, 88 insertions(+), 8 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java index b6f4c7d94..26a551f2a 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java @@ -15,6 +15,7 @@ import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; +import io.papermc.lib.PaperLib; import net.minecraft.core.Holder; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; @@ -179,8 +180,18 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { biomes[layer] = new Holder[64]; } if (biomeData instanceof PalettedContainer> palettedContainer) { - for (int i = 0; i < 64; i++) { - biomes[layer][i] = palettedContainer.get(i); + if (PaperLib.isPaper()) { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = palettedContainer.get(i); // Only public on paper + } + } else { + try { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = (Holder) PaperweightPlatformAdapter.PALETTED_CONTAINER_GET.invoke(i); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } } } else { LOGGER.error( diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java index 23f59e8bf..a56548c46 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java @@ -123,6 +123,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static Field LEVEL_CHUNK_ENTITIES; private static Field SERVER_LEVEL_ENTITY_MANAGER; + static final MethodHandle PALETTED_CONTAINER_GET; + static { final MethodHandles.Lookup lookup = MethodHandles.lookup(); try { @@ -212,6 +214,13 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } catch (NoSuchFieldException ignored) { } POST_CHUNK_REWRITE = chunkRewrite; + + Method palettedContaienrGet = PalettedContainer.class.getDeclaredMethod( + Refraction.pickName("get", "a"), + int.class + ); + palettedContaienrGet.setAccessible(true); + PALETTED_CONTAINER_GET = lookup.unreflect(palettedContaienrGet); } catch (RuntimeException | Error e) { throw e; } catch (Exception e) { diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java index 23c882284..85a8de38b 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java @@ -15,6 +15,7 @@ import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; +import io.papermc.lib.PaperLib; import net.minecraft.core.Holder; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; @@ -179,8 +180,18 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { biomes[layer] = new Holder[64]; } if (biomeData instanceof PalettedContainer> palettedContainer) { - for (int i = 0; i < 64; i++) { - biomes[layer][i] = palettedContainer.get(i); + if (PaperLib.isPaper()) { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = palettedContainer.get(i); // Only public on paper + } + } else { + try { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = (Holder) PaperweightPlatformAdapter.PALETTED_CONTAINER_GET.invoke(i); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } } } else { LOGGER.error( diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java index b69f476d3..76cc25e02 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java @@ -123,6 +123,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static Field LEVEL_CHUNK_ENTITIES; private static Field SERVER_LEVEL_ENTITY_MANAGER; + static final MethodHandle PALETTED_CONTAINER_GET; + static { final MethodHandles.Lookup lookup = MethodHandles.lookup(); try { @@ -212,6 +214,13 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } catch (NoSuchFieldException ignored) { } POST_CHUNK_REWRITE = chunkRewrite; + + Method palettedContaienrGet = PalettedContainer.class.getDeclaredMethod( + Refraction.pickName("get", "a"), + int.class + ); + palettedContaienrGet.setAccessible(true); + PALETTED_CONTAINER_GET = lookup.unreflect(palettedContaienrGet); } catch (RuntimeException | Error e) { throw e; } catch (Exception e) { diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java index 146760020..bb395cbd3 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java @@ -15,6 +15,7 @@ import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; +import io.papermc.lib.PaperLib; import net.minecraft.core.Holder; import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; @@ -180,8 +181,18 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { biomes[layer] = new Holder[64]; } if (biomeData instanceof PalettedContainer> palettedContainer) { - for (int i = 0; i < 64; i++) { - biomes[layer][i] = palettedContainer.get(i); + if (PaperLib.isPaper()) { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = palettedContainer.get(i); // Only public on paper + } + } else { + try { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = (Holder) PaperweightPlatformAdapter.PALETTED_CONTAINER_GET.invoke(i); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } } } else { LOGGER.error( diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java index 03eabc698..df71dae8c 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java @@ -121,6 +121,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static Field LEVEL_CHUNK_ENTITIES; private static Field SERVER_LEVEL_ENTITY_MANAGER; + static final MethodHandle PALETTED_CONTAINER_GET; + static { final MethodHandles.Lookup lookup = MethodHandles.lookup(); try { @@ -210,6 +212,13 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } catch (NoSuchFieldException ignored) { } POST_CHUNK_REWRITE = chunkRewrite; + + Method palettedContaienrGet = PalettedContainer.class.getDeclaredMethod( + Refraction.pickName("get", "a"), + int.class + ); + palettedContaienrGet.setAccessible(true); + PALETTED_CONTAINER_GET = lookup.unreflect(palettedContaienrGet); } catch (RuntimeException | Error e) { throw e; } catch (Exception e) { diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java index a0a4d02d9..1f42361c3 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java @@ -15,6 +15,7 @@ import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; +import io.papermc.lib.PaperLib; import net.minecraft.core.Holder; import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; @@ -180,8 +181,18 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { biomes[layer] = new Holder[64]; } if (biomeData instanceof PalettedContainer> palettedContainer) { - for (int i = 0; i < 64; i++) { - biomes[layer][i] = palettedContainer.get(i); + if (PaperLib.isPaper()) { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = palettedContainer.get(i); // Only public on paper + } + } else { + try { + for (int i = 0; i < 64; i++) { + biomes[layer][i] = (Holder) PaperweightPlatformAdapter.PALETTED_CONTAINER_GET.invoke(i); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } } } else { LOGGER.error( diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java index ab55c7814..b4ed7c8ae 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java @@ -119,6 +119,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { private static Method PAPER_CHUNK_GEN_ALL_ENTITIES; private static Field SERVER_LEVEL_ENTITY_MANAGER; + static final MethodHandle PALETTED_CONTAINER_GET; + static { final MethodHandles.Lookup lookup = MethodHandles.lookup(); try { @@ -195,6 +197,13 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "N")); SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true); } + + Method palettedContaienrGet = PalettedContainer.class.getDeclaredMethod( + Refraction.pickName("get", "a"), + int.class + ); + palettedContaienrGet.setAccessible(true); + PALETTED_CONTAINER_GET = lookup.unreflect(palettedContaienrGet); } catch (RuntimeException | Error e) { throw e; } catch (Exception e) { From 1e8778b528a58707b685739f64e01cac50d0a5ac Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sat, 14 Sep 2024 10:47:37 +0200 Subject: [PATCH 23/59] Avoid deprecated CompoundTag in API (#2883) * Avoid deprecated CompoundTag in API * use javax annotations --- .../v1_20_R2/PaperweightBlockMaterial.java | 12 +- .../fawe/v1_20_R2/PaperweightFaweAdapter.java | 8 ++ .../fawe/v1_20_R2/PaperweightGetBlocks.java | 102 ++++++------- .../v1_20_R2/PaperweightGetBlocks_Copy.java | 53 +++---- .../v1_20_R3/PaperweightBlockMaterial.java | 12 +- .../fawe/v1_20_R3/PaperweightFaweAdapter.java | 8 ++ .../fawe/v1_20_R3/PaperweightGetBlocks.java | 101 ++++++------- .../v1_20_R3/PaperweightGetBlocks_Copy.java | 53 +++---- .../v1_20_R4/PaperweightBlockMaterial.java | 17 ++- .../fawe/v1_20_R4/PaperweightFaweAdapter.java | 8 ++ .../fawe/v1_20_R4/PaperweightGetBlocks.java | 101 ++++++------- .../v1_20_R4/PaperweightGetBlocks_Copy.java | 55 +++---- .../v1_21_R1/PaperweightBlockMaterial.java | 17 ++- .../fawe/v1_21_R1/PaperweightFaweAdapter.java | 8 ++ .../fawe/v1_21_R1/PaperweightGetBlocks.java | 104 +++++++------- .../v1_21_R1/PaperweightGetBlocks_Copy.java | 55 +++---- .../sk89q/worldedit/bukkit/BukkitWorld.java | 4 +- .../bukkit/adapter/BukkitImplLoader.java | 4 +- .../cli/schematic/ClipboardWorld.java | 4 +- .../core/extent/HistoryExtent.java | 8 +- .../clipboard/CPUOptimizedClipboard.java | 8 ++ .../clipboard/DiskOptimizedClipboard.java | 15 +- .../core/extent/clipboard/EmptyClipboard.java | 5 +- .../clipboard/MemoryOptimizedClipboard.java | 8 ++ .../extent/clipboard/ReadOnlyClipboard.java | 4 +- .../clipboard/io/FastSchematicReaderV3.java | 6 +- .../extent/filter/block/ArrayFilterBlock.java | 6 + .../extent/filter/block/CharFilterBlock.java | 34 +++-- .../core/extent/filter/block/FilterBlock.java | 17 +-- .../history/changeset/AbstractChangeSet.java | 127 ++++++++++++----- .../changeset/AbstractDelegateChangeSet.java | 42 +++--- .../history/changeset/BlockBagChangeSet.java | 11 -- .../changeset/FaweStreamChangeSet.java | 40 +++--- .../core/history/changeset/NullChangeSet.java | 10 +- .../core/nbt/EagerFaweCompoundTag.java | 7 + .../core/nbt/FaweCompoundTag.java | 44 ++++++ .../core/nbt/LazyFaweCompoundTag.java | 14 ++ .../core/queue/IBlocks.java | 38 ++++- .../core/queue/IChunkExtent.java | 36 ++--- .../core/queue/IChunkGet.java | 22 ++- .../core/queue/IChunkSet.java | 16 ++- .../core/queue/ITileInput.java | 1 + .../implementation/blocks/BitSetBlocks.java | 15 +- .../implementation/blocks/CharGetBlocks.java | 3 +- .../implementation/blocks/CharSetBlocks.java | 20 +-- .../implementation/blocks/NullChunkGet.java | 28 ++-- .../blocks/ThreadUnsafeCharBlocks.java | 25 ++-- .../implementation/chunk/ChunkHolder.java | 57 ++++---- .../queue/implementation/chunk/NullChunk.java | 52 +++---- .../core/util/MainUtil.java | 5 + .../core/util/NbtUtils.java | 134 +++++++++++++++++- .../core/world/block/CompoundInput.java | 14 ++ .../core/wrappers/WorldWrapper.java | 5 +- .../main/java/com/sk89q/jnbt/NBTUtils.java | 2 + .../extent/AbstractDelegateExtent.java | 5 +- .../com/sk89q/worldedit/extent/Extent.java | 1 - .../sk89q/worldedit/extent/NullExtent.java | 4 +- .../sk89q/worldedit/extent/OutputExtent.java | 20 ++- .../extent/clipboard/BlockArrayClipboard.java | 8 +- .../sk89q/worldedit/math/BlockVector3.java | 1 + .../session/request/RequestExtent.java | 6 +- .../com/sk89q/worldedit/world/NullWorld.java | 4 +- .../worldedit/world/block/BaseBlock.java | 9 +- .../worldedit/world/block/BlockState.java | 7 + .../world/block/BlockStateHolder.java | 5 + .../world/registry/BlockMaterial.java | 15 +- .../registry/PassthroughBlockMaterial.java | 7 + .../world/registry/SimpleBlockMaterial.java | 11 +- 68 files changed, 1096 insertions(+), 612 deletions(-) create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/EagerFaweCompoundTag.java create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/FaweCompoundTag.java create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/LazyFaweCompoundTag.java diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightBlockMaterial.java index a50489b93..1ecdb4116 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightBlockMaterial.java @@ -1,10 +1,8 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.util.ReflectionUtil; import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.world.registry.BlockMaterial; import net.minecraft.core.BlockPos; import net.minecraft.world.level.EmptyBlockGetter; @@ -17,6 +15,8 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.PushReaction; import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData; +import javax.annotation.Nullable; + public class PaperweightBlockMaterial implements BlockMaterial { private final Block block; @@ -25,7 +25,7 @@ public class PaperweightBlockMaterial implements BlockMaterial { private final CraftBlockData craftBlockData; private final org.bukkit.Material craftMaterial; private final int opacity; - private final CompoundTag tile; + private final FaweCompoundTag tile; public PaperweightBlockMaterial(Block block) { this(block, block.defaultBlockState()); @@ -48,7 +48,7 @@ public class PaperweightBlockMaterial implements BlockMaterial { ); tile = tileEntity == null ? null - : new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); + : PaperweightGetBlocks.NMS_TO_TILE.apply(tileEntity); } public Block getBlock() { @@ -173,7 +173,7 @@ public class PaperweightBlockMaterial implements BlockMaterial { } @Override - public CompoundTag getDefaultTile() { + public @Nullable FaweCompoundTag defaultTile() { return tile; } diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweAdapter.java index 53f8ef671..bb2d506f5 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweAdapter.java @@ -5,6 +5,7 @@ import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; @@ -97,6 +98,7 @@ import java.util.Map; import java.util.Objects; import java.util.OptionalInt; import java.util.Set; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -129,6 +131,12 @@ public final class PaperweightFaweAdapter extends FaweAdapter blockEntityToCompoundTag() { + return blockEntity -> FaweCompoundTag.of( + () -> (LinCompoundTag) toNativeLin(blockEntity.saveWithId()) + ); + } + @Nullable private static String getEntityId(Entity entity) { ResourceLocation resourceLocation = net.minecraft.world.entity.EntityType.getKey(entity.getType()); diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java index 93f84a1ec..4bcdee27d 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java @@ -7,20 +7,16 @@ import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.implementation.QueueHandler; import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; import com.fastasyncworldedit.core.util.MathMan; +import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.collection.AdaptedMap; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; @@ -34,6 +30,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.IdMap; import net.minecraft.core.Registry; import net.minecraft.core.SectionPos; +import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.IntTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; @@ -61,11 +58,19 @@ import org.bukkit.World; import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlock; import org.bukkit.event.entity.CreatureSpawnEvent; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTagType; import javax.annotation.Nonnull; -import java.util.AbstractSet; +import javax.annotation.Nullable; +import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -82,7 +87,6 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; -import java.util.stream.Collectors; import static net.minecraft.core.registries.Registries.BIOME; @@ -91,8 +95,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Function posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); - private static final Function nmsTile2We = - tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); + public static final Function NMS_TO_TILE = ((PaperweightFaweAdapter) WorldEditPlugin + .getInstance() + .getBukkitImplAdapter()).blockEntityToCompoundTag(); private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin .getInstance() .getBukkitImplAdapter()); @@ -256,23 +261,24 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getTile(int x, int y, int z) { + public FaweCompoundTag tile(final int x, final int y, final int z) { BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( chunkX << 4), y, (z & 15) + ( chunkZ << 4))); if (blockEntity == null) { return null; } - return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)); + return NMS_TO_TILE.apply(blockEntity); + } @Override - public Map getTiles() { + public Map tiles() { Map nmsTiles = getChunk().getBlockEntities(); if (nmsTiles.isEmpty()) { return Collections.emptyMap(); } - return AdaptedMap.immutable(nmsTiles, posNms2We, nmsTile2We); + return AdaptedMap.immutable(nmsTiles, posNms2We, NMS_TO_TILE); } @Override @@ -335,7 +341,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getEntity(UUID uuid) { + public @Nullable FaweCompoundTag entity(final UUID uuid) { ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); Entity entity = null; @@ -347,10 +353,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (entity != null) { org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); - return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); + return FaweCompoundTag.of(BukkitAdapter.adapt(bukkitEnt).getState().getNbt()); } - for (CompoundTag tag : getEntities()) { - if (uuid.equals(tag.getUUID())) { + for (FaweCompoundTag tag : entities()) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -358,14 +364,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public Set getEntities() { + public Collection entities() { ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); if (entities.isEmpty()) { - return Collections.emptySet(); + return Collections.emptyList(); } int size = entities.size(); - return new AbstractSet<>() { + return new AbstractCollection<>() { @Override public int size() { return size; @@ -378,10 +384,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public boolean contains(Object get) { - if (!(get instanceof CompoundTag getTag)) { + if (!(get instanceof FaweCompoundTag getTag)) { return false; } - UUID getUUID = getTag.getUUID(); + UUID getUUID = NbtUtils.uuid(getTag); for (Entity entity : entities) { UUID uuid = entity.getUUID(); if (uuid.equals(getUUID)) { @@ -393,12 +399,12 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Nonnull @Override - public Iterator iterator() { - Iterable result = entities.stream().map(input -> { - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); + public Iterator iterator() { + Iterable result = entities.stream().map(input -> { + CompoundTag tag = new CompoundTag(); input.save(tag); - return (CompoundTag) adapter.toNative(tag); - }).collect(Collectors.toList()); + return FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(tag)); + })::iterator; return result.iterator(); } }; @@ -728,43 +734,42 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc }; } - Set entities = set.getEntities(); + Collection entities = set.entities(); if (entities != null && !entities.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[2]; } syncTasks[1] = () -> { - Iterator iterator = entities.iterator(); + Iterator iterator = entities.iterator(); while (iterator.hasNext()) { - final CompoundTag nativeTag = iterator.next(); - final Map> entityTagMap = nativeTag.getValue(); - final StringTag idTag = (StringTag) entityTagMap.get("Id"); - final ListTag posTag = (ListTag) entityTagMap.get("Pos"); - final ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); + final FaweCompoundTag nativeTag = iterator.next(); + final LinCompoundTag linTag = nativeTag.linTag(); + final LinStringTag idTag = linTag.findTag("Id", LinTagType.stringTag()); + final LinListTag posTag = linTag.findListTag("Pos", LinTagType.doubleTag()); + final LinListTag rotTag = linTag.findListTag("Rotation", LinTagType.floatTag()); if (idTag == null || posTag == null || rotTag == null) { LOGGER.error("Unknown entity tag: {}", nativeTag); continue; } - final double x = posTag.getDouble(0); - final double y = posTag.getDouble(1); - final double z = posTag.getDouble(2); - final float yaw = rotTag.getFloat(0); - final float pitch = rotTag.getFloat(1); - final String id = idTag.getValue(); + final double x = posTag.get(0).valueAsDouble(); + final double y = posTag.get(1).valueAsDouble(); + final double z = posTag.get(2).valueAsDouble(); + final float yaw = rotTag.get(0).valueAsFloat(); + final float pitch = rotTag.get(1).valueAsFloat(); + final String id = idTag.value(); EntityType type = EntityType.byString(id).orElse(null); if (type != null) { Entity entity = type.create(nmsWorld); if (entity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(linTag); for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); - entity.setUUID(nativeTag.getUUID()); + entity.setUUID(NbtUtils.uuid(nativeTag)); if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", @@ -784,15 +789,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } // set tiles - Map tiles = set.getTiles(); + Map tiles = set.tiles(); if (tiles != null && !tiles.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[1]; } syncTasks[0] = () -> { - for (final Map.Entry entry : tiles.entrySet()) { - final CompoundTag nativeTag = entry.getValue(); + for (final Map.Entry entry : tiles.entrySet()) { + final FaweCompoundTag nativeTag = entry.getValue(); final BlockVector3 blockHash = entry.getKey(); final int x = blockHash.x() + bx; final int y = blockHash.y(); @@ -806,8 +811,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc tileEntity = nmsWorld.getBlockEntity(pos); } if (tileEntity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); tag.put("x", IntTag.valueOf(x)); tag.put("y", IntTag.valueOf(y)); tag.put("z", IntTag.valueOf(z)); diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java index 26a551f2a..e655dd206 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java @@ -1,14 +1,13 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; @@ -17,6 +16,7 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import io.papermc.lib.PaperLib; import net.minecraft.core.Holder; +import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.biome.Biome; @@ -25,9 +25,11 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.PalettedContainerRO; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -39,8 +41,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { private static final Logger LOGGER = LogManagerCompat.getLogger(); - private final Map tiles = new HashMap<>(); - private final Set entities = new HashSet<>(); + private final Map tiles = new HashMap<>(); + private final Set entities = new HashSet<>(); private final char[][] blocks; private final int minHeight; private final int maxHeight; @@ -57,44 +59,35 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } protected void storeTile(BlockEntity blockEntity) { + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); tiles.put( BlockVector3.at( blockEntity.getBlockPos().getX(), blockEntity.getBlockPos().getY(), blockEntity.getBlockPos().getZ() ), - new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)) + FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(blockEntity.saveWithId())) ); } - @Override - public Map getTiles() { - return tiles; - } - - @Override - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return tiles.get(BlockVector3.at(x, y, z)); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) protected void storeEntity(Entity entity) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); entity.save(compoundTag); - entities.add((CompoundTag) adapter.toNative(compoundTag)); + entities.add(FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(compoundTag))); } @Override - public Set getEntities() { + public Collection entities() { return this.entities; } @Override - public CompoundTag getEntity(UUID uuid) { - for (CompoundTag tag : entities) { - if (uuid.equals(tag.getUUID())) { + public @Nullable FaweCompoundTag entity(final UUID uuid) { + for (FaweCompoundTag tag : entities) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -205,7 +198,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public BaseBlock getFullBlock(int x, int y, int z) { BlockState state = BlockTypesCache.states[get(x, y, z)]; - return state.toBaseBlock(this, x, y, z); + return state.toBaseBlock((IBlocks) this, x, y, z); } @Override @@ -235,6 +228,16 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { return BlockTypesCache.states[get(x, y, z)]; } + @Override + public Map tiles() { + return tiles; + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return tiles.get(BlockVector3.at(x, y, z)); + } + @Override public int getSkyLight(int x, int y, int z) { return 0; diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightBlockMaterial.java index 857d09aa6..d4082eb70 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightBlockMaterial.java @@ -1,8 +1,6 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.nbt.PaperweightLazyCompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.world.registry.BlockMaterial; import net.minecraft.core.BlockPos; import net.minecraft.world.level.EmptyBlockGetter; @@ -14,6 +12,8 @@ import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.material.PushReaction; import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData; +import javax.annotation.Nullable; + public class PaperweightBlockMaterial implements BlockMaterial { private final Block block; @@ -21,7 +21,7 @@ public class PaperweightBlockMaterial implements BlockMaterial { private final CraftBlockData craftBlockData; private final org.bukkit.Material craftMaterial; private final int opacity; - private final CompoundTag tile; + private final FaweCompoundTag tile; public PaperweightBlockMaterial(Block block) { this(block, block.defaultBlockState()); @@ -39,7 +39,7 @@ public class PaperweightBlockMaterial implements BlockMaterial { ); tile = tileEntity == null ? null - : new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); + : PaperweightGetBlocks.NMS_TO_TILE.apply(tileEntity); } public Block getBlock() { @@ -163,7 +163,7 @@ public class PaperweightBlockMaterial implements BlockMaterial { } @Override - public CompoundTag getDefaultTile() { + public @Nullable FaweCompoundTag defaultTile() { return tile; } diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweAdapter.java index 30ef3423a..c4af78e95 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweAdapter.java @@ -5,6 +5,7 @@ import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; @@ -97,6 +98,7 @@ import java.util.Map; import java.util.Objects; import java.util.OptionalInt; import java.util.Set; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -129,6 +131,12 @@ public final class PaperweightFaweAdapter extends FaweAdapter blockEntityToCompoundTag() { + return blockEntity -> FaweCompoundTag.of( + () -> (LinCompoundTag) toNativeLin(blockEntity.saveWithId()) + ); + } + @Nullable private static String getEntityId(Entity entity) { ResourceLocation resourceLocation = net.minecraft.world.entity.EntityType.getKey(entity.getType()); diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java index d2d18968a..8bce9c398 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java @@ -7,20 +7,16 @@ import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.implementation.QueueHandler; import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; import com.fastasyncworldedit.core.util.MathMan; +import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.collection.AdaptedMap; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; @@ -34,6 +30,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.IdMap; import net.minecraft.core.Registry; import net.minecraft.core.SectionPos; +import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.IntTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; @@ -61,11 +58,19 @@ import org.bukkit.World; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlock; import org.bukkit.event.entity.CreatureSpawnEvent; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTagType; import javax.annotation.Nonnull; -import java.util.AbstractSet; +import javax.annotation.Nullable; +import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -82,7 +87,6 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; -import java.util.stream.Collectors; import static net.minecraft.core.registries.Registries.BIOME; @@ -91,8 +95,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Function posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); - private static final Function nmsTile2We = - tileEntity -> new PaperweightLazyCompoundTag(Suppliers.memoize(tileEntity::saveWithId)); + public static final Function NMS_TO_TILE = ((PaperweightFaweAdapter) WorldEditPlugin + .getInstance() + .getBukkitImplAdapter()).blockEntityToCompoundTag(); private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin .getInstance() .getBukkitImplAdapter()); @@ -108,6 +113,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; private final ConcurrentHashMap copies = new ConcurrentHashMap<>(); + private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; @@ -255,23 +261,24 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getTile(int x, int y, int z) { + public FaweCompoundTag tile(final int x, final int y, final int z) { BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( chunkX << 4), y, (z & 15) + ( chunkZ << 4))); if (blockEntity == null) { return null; } - return new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)); + return NMS_TO_TILE.apply(blockEntity); + } @Override - public Map getTiles() { + public Map tiles() { Map nmsTiles = getChunk().getBlockEntities(); if (nmsTiles.isEmpty()) { return Collections.emptyMap(); } - return AdaptedMap.immutable(nmsTiles, posNms2We, nmsTile2We); + return AdaptedMap.immutable(nmsTiles, posNms2We, NMS_TO_TILE); } @Override @@ -334,7 +341,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getEntity(UUID uuid) { + public @Nullable FaweCompoundTag entity(final UUID uuid) { ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); Entity entity = null; @@ -346,10 +353,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (entity != null) { org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); - return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); + return FaweCompoundTag.of(BukkitAdapter.adapt(bukkitEnt).getState().getNbt()); } - for (CompoundTag tag : getEntities()) { - if (uuid.equals(tag.getUUID())) { + for (FaweCompoundTag tag : entities()) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -357,14 +364,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public Set getEntities() { + public Collection entities() { ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); if (entities.isEmpty()) { - return Collections.emptySet(); + return Collections.emptyList(); } int size = entities.size(); - return new AbstractSet<>() { + return new AbstractCollection<>() { @Override public int size() { return size; @@ -377,10 +384,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public boolean contains(Object get) { - if (!(get instanceof CompoundTag getTag)) { + if (!(get instanceof FaweCompoundTag getTag)) { return false; } - UUID getUUID = getTag.getUUID(); + UUID getUUID = NbtUtils.uuid(getTag); for (Entity entity : entities) { UUID uuid = entity.getUUID(); if (uuid.equals(getUUID)) { @@ -392,12 +399,12 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Nonnull @Override - public Iterator iterator() { - Iterable result = entities.stream().map(input -> { + public Iterator iterator() { + Iterable result = entities.stream().map(input -> { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); input.save(tag); - return (CompoundTag) adapter.toNative(tag); - }).collect(Collectors.toList()); + return FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(tag)); + })::iterator; return result.iterator(); } }; @@ -727,43 +734,42 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc }; } - Set entities = set.getEntities(); + Collection entities = set.entities(); if (entities != null && !entities.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[2]; } syncTasks[1] = () -> { - Iterator iterator = entities.iterator(); + Iterator iterator = entities.iterator(); while (iterator.hasNext()) { - final CompoundTag nativeTag = iterator.next(); - final Map> entityTagMap = nativeTag.getValue(); - final StringTag idTag = (StringTag) entityTagMap.get("Id"); - final ListTag posTag = (ListTag) entityTagMap.get("Pos"); - final ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); + final FaweCompoundTag nativeTag = iterator.next(); + final LinCompoundTag linTag = nativeTag.linTag(); + final LinStringTag idTag = linTag.findTag("Id", LinTagType.stringTag()); + final LinListTag posTag = linTag.findListTag("Pos", LinTagType.doubleTag()); + final LinListTag rotTag = linTag.findListTag("Rotation", LinTagType.floatTag()); if (idTag == null || posTag == null || rotTag == null) { LOGGER.error("Unknown entity tag: {}", nativeTag); continue; } - final double x = posTag.getDouble(0); - final double y = posTag.getDouble(1); - final double z = posTag.getDouble(2); - final float yaw = rotTag.getFloat(0); - final float pitch = rotTag.getFloat(1); - final String id = idTag.getValue(); + final double x = posTag.get(0).valueAsDouble(); + final double y = posTag.get(1).valueAsDouble(); + final double z = posTag.get(2).valueAsDouble(); + final float yaw = rotTag.get(0).valueAsFloat(); + final float pitch = rotTag.get(1).valueAsFloat(); + final String id = idTag.value(); EntityType type = EntityType.byString(id).orElse(null); if (type != null) { Entity entity = type.create(nmsWorld); if (entity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(linTag); for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); - entity.setUUID(nativeTag.getUUID()); + entity.setUUID(NbtUtils.uuid(nativeTag)); if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", @@ -783,15 +789,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } // set tiles - Map tiles = set.getTiles(); + Map tiles = set.tiles(); if (tiles != null && !tiles.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[1]; } syncTasks[0] = () -> { - for (final Map.Entry entry : tiles.entrySet()) { - final CompoundTag nativeTag = entry.getValue(); + for (final Map.Entry entry : tiles.entrySet()) { + final FaweCompoundTag nativeTag = entry.getValue(); final BlockVector3 blockHash = entry.getKey(); final int x = blockHash.x() + bx; final int y = blockHash.y(); @@ -805,8 +811,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc tileEntity = nmsWorld.getBlockEntity(pos); } if (tileEntity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final net.minecraft.nbt.CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); tag.put("x", IntTag.valueOf(x)); tag.put("y", IntTag.valueOf(y)); tag.put("z", IntTag.valueOf(z)); diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java index 85a8de38b..1163c2d33 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java @@ -1,14 +1,13 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; @@ -17,6 +16,7 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import io.papermc.lib.PaperLib; import net.minecraft.core.Holder; +import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.biome.Biome; @@ -25,9 +25,11 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.PalettedContainerRO; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -39,8 +41,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { private static final Logger LOGGER = LogManagerCompat.getLogger(); - private final Map tiles = new HashMap<>(); - private final Set entities = new HashSet<>(); + private final Map tiles = new HashMap<>(); + private final Set entities = new HashSet<>(); private final char[][] blocks; private final int minHeight; private final int maxHeight; @@ -57,44 +59,35 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } protected void storeTile(BlockEntity blockEntity) { + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); tiles.put( BlockVector3.at( blockEntity.getBlockPos().getX(), blockEntity.getBlockPos().getY(), blockEntity.getBlockPos().getZ() ), - new PaperweightLazyCompoundTag(Suppliers.memoize(blockEntity::saveWithId)) + FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(blockEntity.saveWithId())) ); } - @Override - public Map getTiles() { - return tiles; - } - - @Override - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return tiles.get(BlockVector3.at(x, y, z)); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) protected void storeEntity(Entity entity) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); entity.save(compoundTag); - entities.add((CompoundTag) adapter.toNative(compoundTag)); + entities.add(FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(compoundTag))); } @Override - public Set getEntities() { + public Collection entities() { return this.entities; } @Override - public CompoundTag getEntity(UUID uuid) { - for (CompoundTag tag : entities) { - if (uuid.equals(tag.getUUID())) { + public @Nullable FaweCompoundTag entity(final UUID uuid) { + for (FaweCompoundTag tag : entities) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -205,7 +198,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public BaseBlock getFullBlock(int x, int y, int z) { BlockState state = BlockTypesCache.states[get(x, y, z)]; - return state.toBaseBlock(this, x, y, z); + return state.toBaseBlock((IBlocks) this, x, y, z); } @Override @@ -235,6 +228,16 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { return BlockTypesCache.states[get(x, y, z)]; } + @Override + public Map tiles() { + return tiles; + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return tiles.get(BlockVector3.at(x, y, z)); + } + @Override public int getSkyLight(int x, int y, int z) { return 0; diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java index e80ecf3cb..15f3abbaf 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightBlockMaterial.java @@ -1,11 +1,8 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.world.registry.BlockMaterial; import net.minecraft.core.BlockPos; -import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; @@ -15,6 +12,8 @@ import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.material.PushReaction; import org.bukkit.craftbukkit.block.data.CraftBlockData; +import javax.annotation.Nullable; + public class PaperweightBlockMaterial implements BlockMaterial { private final Block block; @@ -22,7 +21,7 @@ public class PaperweightBlockMaterial implements BlockMaterial { private final CraftBlockData craftBlockData; private final org.bukkit.Material craftMaterial; private final int opacity; - private final CompoundTag tile; + private final FaweCompoundTag tile; public PaperweightBlockMaterial(Block block) { this(block, block.defaultBlockState()); @@ -38,9 +37,9 @@ public class PaperweightBlockMaterial implements BlockMaterial { BlockPos.ZERO, blockState ); - tile = tileEntity == null ? null : new PaperweightLazyCompoundTag( - Suppliers.memoize(() -> tileEntity.saveWithId(DedicatedServer.getServer().registryAccess())) - ); + tile = tileEntity == null + ? null + : PaperweightGetBlocks.NMS_TO_TILE.apply(tileEntity); } public Block getBlock() { @@ -164,7 +163,7 @@ public class PaperweightBlockMaterial implements BlockMaterial { } @Override - public CompoundTag getDefaultTile() { + public @Nullable FaweCompoundTag defaultTile() { return tile; } diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java index 76dc6f951..151ffd1f3 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightFaweAdapter.java @@ -5,6 +5,7 @@ import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; @@ -103,6 +104,7 @@ import java.util.Map; import java.util.Objects; import java.util.OptionalInt; import java.util.Set; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -138,6 +140,12 @@ public final class PaperweightFaweAdapter extends FaweAdapter blockEntityToCompoundTag() { + return blockEntity -> FaweCompoundTag.of( + () -> (LinCompoundTag) toNativeLin(blockEntity.saveWithId(DedicatedServer.getServer().registryAccess())) + ); + } + @Nullable private static String getEntityId(Entity entity) { ResourceLocation resourceLocation = net.minecraft.world.entity.EntityType.getKey(entity.getType()); diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java index 47466ac5e..754b0ab0b 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java @@ -7,20 +7,16 @@ import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.implementation.QueueHandler; import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; import com.fastasyncworldedit.core.util.MathMan; +import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.collection.AdaptedMap; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; @@ -34,6 +30,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.IdMap; import net.minecraft.core.Registry; import net.minecraft.core.SectionPos; +import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.IntTag; import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; @@ -62,11 +59,19 @@ import org.bukkit.World; import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.block.CraftBlock; import org.bukkit.event.entity.CreatureSpawnEvent; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTagType; import javax.annotation.Nonnull; -import java.util.AbstractSet; +import javax.annotation.Nullable; +import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -83,7 +88,6 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; -import java.util.stream.Collectors; import static net.minecraft.core.registries.Registries.BIOME; @@ -92,9 +96,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Function posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); - private static final Function nmsTile2We = tileEntity -> new PaperweightLazyCompoundTag( - Suppliers.memoize(() -> tileEntity.saveWithId(DedicatedServer.getServer().registryAccess())) - ); + public static final Function NMS_TO_TILE = ((PaperweightFaweAdapter) WorldEditPlugin + .getInstance() + .getBukkitImplAdapter()).blockEntityToCompoundTag(); private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin .getInstance() .getBukkitImplAdapter()); @@ -258,23 +262,24 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getTile(int x, int y, int z) { + public FaweCompoundTag tile(final int x, final int y, final int z) { BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( chunkX << 4), y, (z & 15) + ( chunkZ << 4))); if (blockEntity == null) { return null; } - return new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.saveWithId(DedicatedServer.getServer().registryAccess()))); + return NMS_TO_TILE.apply(blockEntity); + } @Override - public Map getTiles() { + public Map tiles() { Map nmsTiles = getChunk().getBlockEntities(); if (nmsTiles.isEmpty()) { return Collections.emptyMap(); } - return AdaptedMap.immutable(nmsTiles, posNms2We, nmsTile2We); + return AdaptedMap.immutable(nmsTiles, posNms2We, NMS_TO_TILE); } @Override @@ -337,7 +342,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getEntity(UUID uuid) { + public @Nullable FaweCompoundTag entity(final UUID uuid) { ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); Entity entity = null; @@ -349,10 +354,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (entity != null) { org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); - return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); + return FaweCompoundTag.of(BukkitAdapter.adapt(bukkitEnt).getState().getNbt()); } - for (CompoundTag tag : getEntities()) { - if (uuid.equals(tag.getUUID())) { + for (FaweCompoundTag tag : entities()) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -360,14 +365,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public Set getEntities() { + public Collection entities() { ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); if (entities.isEmpty()) { - return Collections.emptySet(); + return Collections.emptyList(); } int size = entities.size(); - return new AbstractSet<>() { + return new AbstractCollection<>() { @Override public int size() { return size; @@ -380,10 +385,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public boolean contains(Object get) { - if (!(get instanceof CompoundTag getTag)) { + if (!(get instanceof FaweCompoundTag getTag)) { return false; } - UUID getUUID = getTag.getUUID(); + UUID getUUID = NbtUtils.uuid(getTag); for (Entity entity : entities) { UUID uuid = entity.getUUID(); if (uuid.equals(getUUID)) { @@ -395,12 +400,12 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Nonnull @Override - public Iterator iterator() { - Iterable result = entities.stream().map(input -> { + public Iterator iterator() { + Iterable result = entities.stream().map(input -> { net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); input.save(tag); - return (CompoundTag) adapter.toNative(tag); - }).collect(Collectors.toList()); + return FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(tag)); + })::iterator; return result.iterator(); } }; @@ -728,43 +733,42 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc }; } - Set entities = set.getEntities(); + Collection entities = set.entities(); if (entities != null && !entities.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[2]; } syncTasks[1] = () -> { - Iterator iterator = entities.iterator(); + Iterator iterator = entities.iterator(); while (iterator.hasNext()) { - final CompoundTag nativeTag = iterator.next(); - final Map> entityTagMap = nativeTag.getValue(); - final StringTag idTag = (StringTag) entityTagMap.get("Id"); - final ListTag posTag = (ListTag) entityTagMap.get("Pos"); - final ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); + final FaweCompoundTag nativeTag = iterator.next(); + final LinCompoundTag linTag = nativeTag.linTag(); + final LinStringTag idTag = linTag.findTag("Id", LinTagType.stringTag()); + final LinListTag posTag = linTag.findListTag("Pos", LinTagType.doubleTag()); + final LinListTag rotTag = linTag.findListTag("Rotation", LinTagType.floatTag()); if (idTag == null || posTag == null || rotTag == null) { LOGGER.error("Unknown entity tag: {}", nativeTag); continue; } - final double x = posTag.getDouble(0); - final double y = posTag.getDouble(1); - final double z = posTag.getDouble(2); - final float yaw = rotTag.getFloat(0); - final float pitch = rotTag.getFloat(1); - final String id = idTag.getValue(); + final double x = posTag.get(0).valueAsDouble(); + final double y = posTag.get(1).valueAsDouble(); + final double z = posTag.get(2).valueAsDouble(); + final float yaw = rotTag.get(0).valueAsFloat(); + final float pitch = rotTag.get(1).valueAsFloat(); + final String id = idTag.value(); EntityType type = EntityType.byString(id).orElse(null); if (type != null) { Entity entity = type.create(nmsWorld); if (entity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(linTag); for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); - entity.setUUID(nativeTag.getUUID()); + entity.setUUID(NbtUtils.uuid(nativeTag)); if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", @@ -784,15 +788,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } // set tiles - Map tiles = set.getTiles(); + Map tiles = set.tiles(); if (tiles != null && !tiles.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[1]; } syncTasks[0] = () -> { - for (final Map.Entry entry : tiles.entrySet()) { - final CompoundTag nativeTag = entry.getValue(); + for (final Map.Entry entry : tiles.entrySet()) { + final FaweCompoundTag nativeTag = entry.getValue(); final BlockVector3 blockHash = entry.getKey(); final int x = blockHash.x() + bx; final int y = blockHash.y(); @@ -806,8 +810,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc tileEntity = nmsWorld.getBlockEntity(pos); } if (tileEntity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final net.minecraft.nbt.CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); tag.put("x", IntTag.valueOf(x)); tag.put("y", IntTag.valueOf(y)); tag.put("z", IntTag.valueOf(z)); diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java index bb395cbd3..7d199c7f6 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java @@ -1,14 +1,13 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; @@ -17,6 +16,7 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import io.papermc.lib.PaperLib; import net.minecraft.core.Holder; +import net.minecraft.nbt.Tag; import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; @@ -26,9 +26,11 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.PalettedContainerRO; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -40,8 +42,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { private static final Logger LOGGER = LogManagerCompat.getLogger(); - private final Map tiles = new HashMap<>(); - private final Set entities = new HashSet<>(); + private final Map tiles = new HashMap<>(); + private final Set entities = new HashSet<>(); private final char[][] blocks; private final int minHeight; private final int maxHeight; @@ -58,44 +60,37 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } protected void storeTile(BlockEntity blockEntity) { + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); tiles.put( BlockVector3.at( blockEntity.getBlockPos().getX(), blockEntity.getBlockPos().getY(), blockEntity.getBlockPos().getZ() ), - new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.saveWithId(DedicatedServer.getServer().registryAccess()))) + FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(blockEntity.saveWithId(DedicatedServer + .getServer() + .registryAccess()))) ); } - @Override - public Map getTiles() { - return tiles; - } - - @Override - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return tiles.get(BlockVector3.at(x, y, z)); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) protected void storeEntity(Entity entity) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); entity.save(compoundTag); - entities.add((CompoundTag) adapter.toNative(compoundTag)); + entities.add(FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(compoundTag))); } @Override - public Set getEntities() { + public Collection entities() { return this.entities; } @Override - public CompoundTag getEntity(UUID uuid) { - for (CompoundTag tag : entities) { - if (uuid.equals(tag.getUUID())) { + public @Nullable FaweCompoundTag entity(final UUID uuid) { + for (FaweCompoundTag tag : entities) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -206,7 +201,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public BaseBlock getFullBlock(int x, int y, int z) { BlockState state = BlockTypesCache.states[get(x, y, z)]; - return state.toBaseBlock(this, x, y, z); + return state.toBaseBlock((IBlocks) this, x, y, z); } @Override @@ -236,6 +231,16 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { return BlockTypesCache.states[get(x, y, z)]; } + @Override + public Map tiles() { + return tiles; + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return tiles.get(BlockVector3.at(x, y, z)); + } + @Override public int getSkyLight(int x, int y, int z) { return 0; diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java index 537072538..d48e5fe1d 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightBlockMaterial.java @@ -1,11 +1,8 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt.PaperweightLazyCompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.world.registry.BlockMaterial; import net.minecraft.core.BlockPos; -import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.world.level.EmptyBlockGetter; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; @@ -15,6 +12,8 @@ import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.material.PushReaction; import org.bukkit.craftbukkit.block.data.CraftBlockData; +import javax.annotation.Nullable; + public class PaperweightBlockMaterial implements BlockMaterial { private final Block block; @@ -22,7 +21,7 @@ public class PaperweightBlockMaterial implements BlockMaterial { private final CraftBlockData craftBlockData; private final org.bukkit.Material craftMaterial; private final int opacity; - private final CompoundTag tile; + private final FaweCompoundTag tile; public PaperweightBlockMaterial(Block block) { this(block, block.defaultBlockState()); @@ -38,9 +37,9 @@ public class PaperweightBlockMaterial implements BlockMaterial { BlockPos.ZERO, blockState ); - tile = tileEntity == null ? null : new PaperweightLazyCompoundTag( - Suppliers.memoize(() -> tileEntity.saveWithId(DedicatedServer.getServer().registryAccess())) - ); + tile = tileEntity == null + ? null + : PaperweightGetBlocks.NMS_TO_TILE.apply(tileEntity); } public Block getBlock() { @@ -164,7 +163,7 @@ public class PaperweightBlockMaterial implements BlockMaterial { } @Override - public CompoundTag getDefaultTile() { + public @Nullable FaweCompoundTag defaultTile() { return tile; } diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweAdapter.java index 11577ca9e..9452024c5 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweAdapter.java @@ -5,6 +5,7 @@ import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; @@ -102,6 +103,7 @@ import java.util.Map; import java.util.Objects; import java.util.OptionalInt; import java.util.Set; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -137,6 +139,12 @@ public final class PaperweightFaweAdapter extends FaweAdapter blockEntityToCompoundTag() { + return blockEntity -> FaweCompoundTag.of( + () -> (LinCompoundTag) toNativeLin(blockEntity.saveWithId(DedicatedServer.getServer().registryAccess())) + ); + } + @Nullable private static String getEntityId(Entity entity) { ResourceLocation resourceLocation = net.minecraft.world.entity.EntityType.getKey(entity.getType()); diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java index bdd9d0648..6ef85090f 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java @@ -7,20 +7,16 @@ import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.implementation.QueueHandler; import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; import com.fastasyncworldedit.core.util.MathMan; +import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.collection.AdaptedMap; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; @@ -34,6 +30,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.IdMap; import net.minecraft.core.Registry; import net.minecraft.core.SectionPos; +import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.IntTag; import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; @@ -62,11 +59,19 @@ import org.bukkit.World; import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.block.CraftBlock; import org.bukkit.event.entity.CreatureSpawnEvent; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinFloatTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTagType; import javax.annotation.Nonnull; -import java.util.AbstractSet; +import javax.annotation.Nullable; +import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -83,7 +88,6 @@ import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; -import java.util.stream.Collectors; import static net.minecraft.core.registries.Registries.BIOME; @@ -92,9 +96,9 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Function posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); - private static final Function nmsTile2We = tileEntity -> new PaperweightLazyCompoundTag( - Suppliers.memoize(() -> tileEntity.saveWithId(DedicatedServer.getServer().registryAccess())) - ); + public static final Function NMS_TO_TILE = ((PaperweightFaweAdapter) WorldEditPlugin + .getInstance() + .getBukkitImplAdapter()).blockEntityToCompoundTag(); private final PaperweightFaweAdapter adapter = ((PaperweightFaweAdapter) WorldEditPlugin .getInstance() .getBukkitImplAdapter()); @@ -258,23 +262,24 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getTile(int x, int y, int z) { + public FaweCompoundTag tile(final int x, final int y, final int z) { BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( chunkX << 4), y, (z & 15) + ( chunkZ << 4))); if (blockEntity == null) { return null; } - return new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.saveWithId(DedicatedServer.getServer().registryAccess()))); + return NMS_TO_TILE.apply(blockEntity); + } @Override - public Map getTiles() { + public Map tiles() { Map nmsTiles = getChunk().getBlockEntities(); if (nmsTiles.isEmpty()) { return Collections.emptyMap(); } - return AdaptedMap.immutable(nmsTiles, posNms2We, nmsTile2We); + return AdaptedMap.immutable(nmsTiles, posNms2We, NMS_TO_TILE); } @Override @@ -337,7 +342,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public CompoundTag getEntity(UUID uuid) { + public @Nullable FaweCompoundTag entity(final UUID uuid) { ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); Entity entity = null; @@ -349,10 +354,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (entity != null) { org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); - return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); + return FaweCompoundTag.of(BukkitAdapter.adapt(bukkitEnt).getState().getNbt()); } - for (CompoundTag tag : getEntities()) { - if (uuid.equals(tag.getUUID())) { + for (FaweCompoundTag tag : entities()) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -360,14 +365,14 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public Set getEntities() { + public Collection entities() { ensureLoaded(serverLevel, chunkX, chunkZ); List entities = PaperweightPlatformAdapter.getEntities(getChunk()); if (entities.isEmpty()) { - return Collections.emptySet(); + return Collections.emptyList(); } int size = entities.size(); - return new AbstractSet<>() { + return new AbstractCollection<>() { @Override public int size() { return size; @@ -380,10 +385,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public boolean contains(Object get) { - if (!(get instanceof CompoundTag getTag)) { + if (!(get instanceof FaweCompoundTag getTag)) { return false; } - UUID getUUID = getTag.getUUID(); + UUID getUUID = NbtUtils.uuid(getTag); for (Entity entity : entities) { UUID uuid = entity.getUUID(); if (uuid.equals(getUUID)) { @@ -395,15 +400,16 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Nonnull @Override - public Iterator iterator() { - Iterable result = entities.stream().map(input -> { - net.minecraft.nbt.CompoundTag tag = new net.minecraft.nbt.CompoundTag(); + public Iterator iterator() { + Iterable result = entities.stream().map(input -> { + CompoundTag tag = new CompoundTag(); input.save(tag); - return (CompoundTag) adapter.toNative(tag); - }).collect(Collectors.toList()); + return FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(tag)); + })::iterator; return result.iterator(); } }; + } private void removeEntity(Entity entity) { @@ -722,43 +728,42 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc }; } - Set entities = set.getEntities(); + Collection entities = set.entities(); if (entities != null && !entities.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[2]; } syncTasks[1] = () -> { - Iterator iterator = entities.iterator(); + Iterator iterator = entities.iterator(); while (iterator.hasNext()) { - final CompoundTag nativeTag = iterator.next(); - final Map> entityTagMap = nativeTag.getValue(); - final StringTag idTag = (StringTag) entityTagMap.get("Id"); - final ListTag posTag = (ListTag) entityTagMap.get("Pos"); - final ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); + final FaweCompoundTag nativeTag = iterator.next(); + final LinCompoundTag linTag = nativeTag.linTag(); + final LinStringTag idTag = linTag.findTag("Id", LinTagType.stringTag()); + final LinListTag posTag = linTag.findListTag("Pos", LinTagType.doubleTag()); + final LinListTag rotTag = linTag.findListTag("Rotation", LinTagType.floatTag()); if (idTag == null || posTag == null || rotTag == null) { LOGGER.error("Unknown entity tag: {}", nativeTag); continue; } - final double x = posTag.getDouble(0); - final double y = posTag.getDouble(1); - final double z = posTag.getDouble(2); - final float yaw = rotTag.getFloat(0); - final float pitch = rotTag.getFloat(1); - final String id = idTag.getValue(); + final double x = posTag.get(0).valueAsDouble(); + final double y = posTag.get(1).valueAsDouble(); + final double z = posTag.get(2).valueAsDouble(); + final float yaw = rotTag.get(0).valueAsFloat(); + final float pitch = rotTag.get(1).valueAsFloat(); + final String id = idTag.value(); EntityType type = EntityType.byString(id).orElse(null); if (type != null) { Entity entity = type.create(nmsWorld); if (entity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(linTag); for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); - entity.setUUID(nativeTag.getUUID()); + entity.setUUID(NbtUtils.uuid(nativeTag)); if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", @@ -778,15 +783,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } // set tiles - Map tiles = set.getTiles(); + Map tiles = set.tiles(); if (tiles != null && !tiles.isEmpty()) { if (syncTasks == null) { syncTasks = new Runnable[1]; } syncTasks[0] = () -> { - for (final Map.Entry entry : tiles.entrySet()) { - final CompoundTag nativeTag = entry.getValue(); + for (final Map.Entry entry : tiles.entrySet()) { + final FaweCompoundTag nativeTag = entry.getValue(); final BlockVector3 blockHash = entry.getKey(); final int x = blockHash.x() + bx; final int y = blockHash.y(); @@ -800,8 +805,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc tileEntity = nmsWorld.getBlockEntity(pos); } if (tileEntity != null) { - final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNative( - nativeTag); + final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); tag.put("x", IntTag.valueOf(x)); tag.put("y", IntTag.valueOf(y)); tag.put("z", IntTag.valueOf(z)); diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java index 1f42361c3..18b557b97 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java @@ -1,14 +1,13 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.google.common.base.Suppliers; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; @@ -17,6 +16,7 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import io.papermc.lib.PaperLib; import net.minecraft.core.Holder; +import net.minecraft.nbt.Tag; import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; @@ -26,9 +26,11 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.PalettedContainer; import net.minecraft.world.level.chunk.PalettedContainerRO; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nullable; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -40,8 +42,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { private static final Logger LOGGER = LogManagerCompat.getLogger(); - private final Map tiles = new HashMap<>(); - private final Set entities = new HashSet<>(); + private final Map tiles = new HashMap<>(); + private final Set entities = new HashSet<>(); private final char[][] blocks; private final int minHeight; private final int maxHeight; @@ -58,44 +60,37 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } protected void storeTile(BlockEntity blockEntity) { + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); tiles.put( BlockVector3.at( blockEntity.getBlockPos().getX(), blockEntity.getBlockPos().getY(), blockEntity.getBlockPos().getZ() ), - new PaperweightLazyCompoundTag(Suppliers.memoize(() -> blockEntity.saveWithId(DedicatedServer.getServer().registryAccess()))) + FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(blockEntity.saveWithId(DedicatedServer + .getServer() + .registryAccess()))) ); } - @Override - public Map getTiles() { - return tiles; - } - - @Override - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return tiles.get(BlockVector3.at(x, y, z)); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) protected void storeEntity(Entity entity) { - BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); + @SuppressWarnings("unchecked") + BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); net.minecraft.nbt.CompoundTag compoundTag = new net.minecraft.nbt.CompoundTag(); entity.save(compoundTag); - entities.add((CompoundTag) adapter.toNative(compoundTag)); + entities.add(FaweCompoundTag.of((LinCompoundTag) adapter.toNativeLin(compoundTag))); } @Override - public Set getEntities() { + public Collection entities() { return this.entities; } @Override - public CompoundTag getEntity(UUID uuid) { - for (CompoundTag tag : entities) { - if (uuid.equals(tag.getUUID())) { + public @Nullable FaweCompoundTag entity(final UUID uuid) { + for (FaweCompoundTag tag : entities) { + if (uuid.equals(NbtUtils.uuid(tag))) { return tag; } } @@ -206,7 +201,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public BaseBlock getFullBlock(int x, int y, int z) { BlockState state = BlockTypesCache.states[get(x, y, z)]; - return state.toBaseBlock(this, x, y, z); + return state.toBaseBlock((IBlocks) this, x, y, z); } @Override @@ -236,6 +231,16 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { return BlockTypesCache.states[get(x, y, z)]; } + @Override + public Map tiles() { + return tiles; + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return tiles.get(BlockVector3.at(x, y, z)); + } + @Override public int getSkyLight(int x, int y, int z) { return 0; diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 66507c151..55912d770 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -24,12 +24,12 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.internal.exception.FaweException; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; @@ -665,7 +665,7 @@ public class BukkitWorld extends AbstractWorld { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { return false; } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java index 5cf783350..f55029ac4 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplLoader.java @@ -165,9 +165,11 @@ public class BukkitImplLoader { * @throws AdapterLoadException thrown if no adapter could be found */ public BukkitImplAdapter loadAdapter() throws AdapterLoadException { + // FAWE - do not initialize classes on lookup + final ClassLoader classLoader = this.getClass().getClassLoader(); for (String className : adapterCandidates) { try { - Class cls = Class.forName(className); + Class cls = Class.forName(className, false, classLoader); if (cls.isSynthetic()) { continue; } diff --git a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/schematic/ClipboardWorld.java b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/schematic/ClipboardWorld.java index e0b4c64f2..1502fdbf3 100644 --- a/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/schematic/ClipboardWorld.java +++ b/worldedit-cli/src/main/java/com/sk89q/worldedit/cli/schematic/ClipboardWorld.java @@ -19,10 +19,10 @@ package com.sk89q.worldedit.cli.schematic; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.google.common.collect.ImmutableSet; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; @@ -193,7 +193,7 @@ public class ClipboardWorld extends AbstractWorld implements Clipboard, CLIWorld } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { return false; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HistoryExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HistoryExtent.java index daad170da..720b5e57b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HistoryExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HistoryExtent.java @@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.extent; import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet; import com.fastasyncworldedit.core.math.MutableBlockVector3; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; @@ -74,7 +75,7 @@ public class HistoryExtent extends AbstractDelegateExtent { public Entity createEntity(Location location, BaseEntity state) { final Entity entity = super.createEntity(location, state); if (state != null) { - this.changeSet.addEntityCreate(state.getNbtData()); + this.changeSet.addEntityCreate(FaweCompoundTag.of(state.getNbt())); } return entity; } @@ -84,7 +85,7 @@ public class HistoryExtent extends AbstractDelegateExtent { public Entity createEntity(Location location, BaseEntity state, UUID uuid) { final Entity entity = super.createEntity(location, state, uuid); if (state != null) { - this.changeSet.addEntityCreate(state.getNbtData()); + this.changeSet.addEntityCreate(FaweCompoundTag.of(state.getNbt())); } return entity; } @@ -154,11 +155,10 @@ public class HistoryExtent extends AbstractDelegateExtent { @Override public boolean remove() { - final Location location = this.entity.getLocation(); final BaseEntity state = this.entity.getState(); final boolean success = this.entity.remove(); if (state != null && success) { - HistoryExtent.this.changeSet.addEntityRemove(state.getNbtData()); + HistoryExtent.this.changeSet.addEntityRemove(FaweCompoundTag.of(state.getNbt())); } return success; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/CPUOptimizedClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/CPUOptimizedClipboard.java index 77447ac4c..ef7cc0461 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/CPUOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/CPUOptimizedClipboard.java @@ -2,9 +2,11 @@ package com.fastasyncworldedit.core.extent.clipboard; import com.fastasyncworldedit.core.jnbt.streamer.IntValueReader; import com.fastasyncworldedit.core.math.IntTriple; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.biome.BiomeType; @@ -175,6 +177,12 @@ public class CPUOptimizedClipboard extends LinearClipboard { return true; } + @Override + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { + // TODO replace + return setTile(x, y, z, new CompoundTag(tile.linTag())); + } + private boolean setTile(int index, CompoundTag tag) { final Map> values = new HashMap<>(tag.getValue()); values.remove("x"); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java index dc7193394..c81059ccb 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java @@ -6,15 +6,17 @@ import com.fastasyncworldedit.core.internal.exception.FaweClipboardVersionMismat import com.fastasyncworldedit.core.internal.io.ByteBufferInputStream; import com.fastasyncworldedit.core.jnbt.streamer.IntValueReader; import com.fastasyncworldedit.core.math.IntTriple; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.util.MainUtil; +import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.ReflectionUtils; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.DoubleTag; -import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.internal.util.LogManagerCompat; @@ -65,6 +67,7 @@ public class DiskOptimizedClipboard extends LinearClipboard { private static final Map LOCK_HOLDER_CACHE = new ConcurrentHashMap<>(); private final HashMap nbtMap; + private final HashMap nbtMap2; private final File file; private final int headerSize; @@ -124,6 +127,7 @@ public class DiskOptimizedClipboard extends LinearClipboard { canHaveBiomes = false; } nbtMap = new HashMap<>(); + nbtMap2 = new HashMap<>(); try { this.file = file; try { @@ -180,6 +184,7 @@ public class DiskOptimizedClipboard extends LinearClipboard { super(readSize(file, versionOverride), BlockVector3.ZERO); headerSize = getHeaderSizeOverrideFromVersion(versionOverride); nbtMap = new HashMap<>(); + nbtMap2 = new HashMap<>(); try { this.file = file; this.braf = new RandomAccessFile(file, "rw"); @@ -709,12 +714,8 @@ public class DiskOptimizedClipboard extends LinearClipboard { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tag) { - final Map> values = new HashMap<>(tag.getValue()); - values.put("x", new IntTag(x)); - values.put("y", new IntTag(y)); - values.put("z", new IntTag(z)); - nbtMap.put(new IntTriple(x, y, z), new CompoundTag(values)); + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { + nbtMap2.put(new IntTriple(x, y, z), NbtUtils.withPosition(tile, x, y, z)); return true; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/EmptyClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/EmptyClipboard.java index 8e18c2c19..983ea79b0 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/EmptyClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/EmptyClipboard.java @@ -1,7 +1,7 @@ package com.fastasyncworldedit.core.extent.clipboard; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.clipboard.Clipboard; @@ -84,7 +84,8 @@ public final class EmptyClipboard implements Clipboard { return false; } - public boolean setTile(int x, int y, int z, @Nonnull CompoundTag tile) throws WorldEditException { + @Override + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { return false; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/MemoryOptimizedClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/MemoryOptimizedClipboard.java index 426cbc32a..c113c720c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/MemoryOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/MemoryOptimizedClipboard.java @@ -3,10 +3,12 @@ package com.fastasyncworldedit.core.extent.clipboard; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.jnbt.streamer.IntValueReader; import com.fastasyncworldedit.core.math.IntTriple; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.util.MainUtil; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.biome.BiomeType; @@ -262,6 +264,12 @@ public class MemoryOptimizedClipboard extends LinearClipboard { return true; } + @Override + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { + // TODO replace + return setTile(x, y, z, new CompoundTag(tile.linTag())); + } + @Override public > boolean setBlock(int x, int y, int z, B block) { return setBlock(getIndex(x, y, z), block); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ReadOnlyClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ReadOnlyClipboard.java index 2edb9cb51..aa608be05 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ReadOnlyClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/ReadOnlyClipboard.java @@ -1,7 +1,7 @@ package com.fastasyncworldedit.core.extent.clipboard; import com.fastasyncworldedit.core.Fawe; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; @@ -106,7 +106,7 @@ public abstract class ReadOnlyClipboard extends SimpleClipboard { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tag) { + public boolean tile(int x, int y, int z, FaweCompoundTag tag) { throw new UnsupportedOperationException("Clipboard is immutable"); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV3.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV3.java index 8b6aa6cc8..55e249740 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV3.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV3.java @@ -5,6 +5,7 @@ import com.fastasyncworldedit.core.extent.clipboard.SimpleClipboard; import com.fastasyncworldedit.core.internal.io.ResettableFileInputStream; import com.fastasyncworldedit.core.internal.io.VarIntStreamIterator; import com.fastasyncworldedit.core.math.MutableBlockVector3; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.util.IOUtil; import com.fastasyncworldedit.core.util.MathMan; import com.sk89q.jnbt.CompoundTag; @@ -626,12 +627,11 @@ public class FastSchematicReaderV3 implements ClipboardReader { } private EntityTransformer provideTileEntityTransformer(Clipboard clipboard) { - //noinspection deprecation - return (x, y, z, id, tag) -> clipboard.setTile( + return (x, y, z, id, tag) -> clipboard.tile( MathMan.roundInt(x + clipboard.getMinimumPoint().x()), MathMan.roundInt(y + clipboard.getMinimumPoint().y()), MathMan.roundInt(z + clipboard.getMinimumPoint().z()), - new CompoundTag(tag) + FaweCompoundTag.of(tag) ); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ArrayFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ArrayFilterBlock.java index 362f869ac..2e9263cea 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ArrayFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ArrayFilterBlock.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.core.extent.filter.block; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; @@ -105,6 +106,11 @@ public class ArrayFilterBlock extends AbstractExtentFilterBlock { return getExtent().setBlock(x, y, z, block); } + @Override + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { + return false; // class is unused + deprecated, do not care about impl + } + @Override public boolean setBiome(int x, int y, int z, BiomeType biome) { return getExtent().setBiome(x, y, z, biome); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java index 579f04a9a..b1862987f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java @@ -1,6 +1,7 @@ package com.fastasyncworldedit.core.extent.filter.block; import com.fastasyncworldedit.core.FaweCache; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.FilterBlockMask; import com.fastasyncworldedit.core.queue.IBlocks; @@ -13,6 +14,7 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.concurrency.LazyReference; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -20,6 +22,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.registry.BlockMaterial; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -259,8 +262,9 @@ public class CharFilterBlock extends ChunkFilterBlock { final BlockState state = getBlock(); final BlockMaterial material = state.getMaterial(); if (material.hasContainer()) { - final CompoundTag tag = get.getTile(x, y + yy, z); - return state.toBaseBlock(tag); + final FaweCompoundTag tag = get.tile(x, y + yy, z); + assert tag != null : "has container but is null"; + return state.toBaseBlock(tag.linTag()); } return state.toBaseBlock(); } @@ -268,16 +272,28 @@ public class CharFilterBlock extends ChunkFilterBlock { @Override public void setFullBlock(BaseBlock block) { delegate.set(this, block.getOrdinalChar()); - final CompoundTag nbt = block.getNbtData(); + final LazyReference nbt = block.getNbtReference(); if (nbt != null) { // TODO optimize check via ImmutableBaseBlock - set.setTile(x, yy + y, z, nbt); + set.tile(x, yy + y, z, FaweCompoundTag.of(nbt)); } } @Override - public final CompoundTag getNbtData() { - return get.getTile(x, y + yy, z); + public @Nullable LinCompoundTag getNbt() { + final FaweCompoundTag tile = get.tile(x, y + yy, z); + if (tile == null) { + return null; + } + return tile.linTag(); } + + @Override + public void setNbt(@Nullable final LinCompoundTag nbtData) { + if (nbtData != null) { + set.tile(x, y + yy, z, FaweCompoundTag.of(nbtData)); + } + } + /* NORTH(Vector3.at(0, 0, -1), Flag.CARDINAL, 3, 1), EAST(Vector3.at(1, 0, 0), Flag.CARDINAL, 0, 2), @@ -286,9 +302,9 @@ public class CharFilterBlock extends ChunkFilterBlock { */ @Override - public void setNbtData(CompoundTag tag) { - if (tag != null) { - set.setTile(x, y + yy, z, tag); + public void setNbtReference(@Nullable final LazyReference nbtData) { + if (nbtData != null) { + set.tile(x, y + yy, z, FaweCompoundTag.of(nbtData)); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/FilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/FilterBlock.java index 3565c696f..c35f549a2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/FilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/FilterBlock.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.core.extent.filter.block; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.TileEntityBlock; @@ -35,17 +36,6 @@ public abstract class FilterBlock extends BlockVector3 implements Extent, TileEn public abstract BiomeType getBiome(); - @Override - public abstract CompoundTag getNbtData(); - - @Override - public abstract void setNbtData(@Nullable CompoundTag nbtData); - - @Override - public boolean hasNbtData() { - return getNbtData() != null; - } - @Override public BlockVector3 getMinimumPoint() { return getExtent().getMinimumPoint(); @@ -61,10 +51,9 @@ public abstract class FilterBlock extends BlockVector3 implements Extent, TileEn return getExtent().getBlock(x, y, z); } - @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { - return getExtent().setTile(x, y, z, tile); + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { + return getExtent().tile(x, y, z, tile); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java index 84c1193eb..3e60cb4eb 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java @@ -4,11 +4,12 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.extent.HistoryExtent; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.fastasyncworldedit.core.util.MainUtil; +import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.util.concurrent.Futures; import com.sk89q.jnbt.CompoundTag; @@ -32,9 +33,12 @@ import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; import org.jetbrains.annotations.ApiStatus; +import javax.annotation.Nonnull; import java.io.IOException; +import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Objects; @@ -123,37 +127,38 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { int bx = chunk.getX() << 4; int bz = chunk.getZ() << 4; - Map tilesFrom = get.getTiles(); - Map tilesTo = set.getTiles(); + Map tilesFrom = get.tiles(); + Map tilesTo = set.tiles(); if (!tilesFrom.isEmpty()) { - for (Map.Entry entry : tilesFrom.entrySet()) { + for (Map.Entry entry : tilesFrom.entrySet()) { BlockVector3 pos = entry.getKey(); BlockState fromBlock = get.getBlock(pos.x() & 15, pos.y(), pos.z() & 15); BlockState toBlock = set.getBlock(pos.x() & 15, pos.y(), pos.z() & 15); if (fromBlock != toBlock || tilesTo.containsKey(pos)) { - addTileRemove(MainUtil.setPosition(entry.getValue(), entry.getKey().x(), entry.getKey().y(), - entry.getKey().z())); + addTileRemove(NbtUtils.withPosition(entry.getValue(), entry.getKey().x(), entry.getKey().y(), + entry.getKey().z() + )); } } } if (!tilesTo.isEmpty()) { - for (Map.Entry entry : tilesTo.entrySet()) { + for (Map.Entry entry : tilesTo.entrySet()) { BlockVector3 pos = entry.getKey(); - addTileCreate(MainUtil.setPosition(entry.getValue(), pos.x() + bx, pos.y(), pos.z() + bz)); + addTileCreate(NbtUtils.withPosition(entry.getValue(), pos.x() + bx, pos.y(), pos.z() + bz)); } } Set entRemoves = set.getEntityRemoves(); if (!entRemoves.isEmpty()) { for (UUID uuid : entRemoves) { - CompoundTag found = get.getEntity(uuid); + FaweCompoundTag found = get.entity(uuid); if (found != null) { addEntityRemove(found); } } } - Set ents = set.getEntities(); + Collection ents = set.entities(); if (!ents.isEmpty()) { - for (CompoundTag tag : ents) { + for (FaweCompoundTag tag : ents) { addEntityCreate(tag); } } @@ -204,9 +209,9 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { BiomeType[] biomeSection = biomes[layer - set.getMinSectionPosition()]; int index = 0; int yy = layer << 4; - for (int y = 0; y < 16; y+= 4) { - for (int z = 0; z < 16; z+= 4) { - for (int x = 0; x < 16; x+= 4, index++) { + for (int y = 0; y < 16; y += 4) { + for (int z = 0; z < 16; z += 4) { + for (int x = 0; x < 16; x += 4, index++) { BiomeType newBiome = biomeSection[index]; if (newBiome != null) { BiomeType oldBiome = get.getBiomeType(x, yy + y, z); @@ -237,13 +242,62 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { return ProcessorScope.READING_SET_BLOCKS; } - public abstract void addTileCreate(CompoundTag tag); + @Deprecated(forRemoval = true, since = "TODO") + public void addTileCreate(CompoundTag tag) { + addTileCreate(adapt(tag)); + } - public abstract void addTileRemove(CompoundTag tag); + @SuppressWarnings({"deprecation"}) + private static @Nonnull FaweCompoundTag adapt(CompoundTag tag) { + return FaweCompoundTag.of(tag.toLinTag()); + } - public abstract void addEntityRemove(CompoundTag tag); + /** + * Creates a tile/block entity create change to this change set. + * + * @param tag the tile/block entity to add. + * @since TODO + */ + public abstract void addTileCreate(FaweCompoundTag tag); - public abstract void addEntityCreate(CompoundTag tag); + @Deprecated(forRemoval = true, since = "TODO") + public void addTileRemove(CompoundTag tag) { + addTileRemove(adapt(tag)); + } + + /** + * Creates a tile/block entity remove change to this change set. + * + * @param tag the tile/block entity to remove. + * @since TODO + */ + public abstract void addTileRemove(FaweCompoundTag tag); + + @Deprecated(forRemoval = true, since = "TODO") + public void addEntityRemove(CompoundTag tag) { + addEntityRemove(adapt(tag)); + } + + /** + * Creates an entity remove change to this change set. + * + * @param tag the entity to remove. + * @since TODO + */ + public abstract void addEntityRemove(FaweCompoundTag tag); + + @Deprecated(forRemoval = true, since = "TODO") + public void addEntityCreate(CompoundTag tag) { + addEntityCreate(adapt(tag)); + } + + /** + * Creates an entity create change to this change set. + * + * @param tag the entity to add. + * @since TODO + */ + public abstract void addEntityCreate(FaweCompoundTag tag); public abstract void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to); @@ -280,13 +334,15 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { } public void add(EntityCreate change) { - CompoundTag tag = change.state.getNbtData(); - addEntityCreate(MainUtil.setEntityInfo(tag, change.getEntity())); + LinCompoundTag tag = change.state.getNbt(); + assert tag != null; + addEntityCreate(FaweCompoundTag.of(NbtUtils.withEntityInfo(tag, change.getEntity()))); } public void add(EntityRemove change) { - CompoundTag tag = change.state.getNbtData(); - addEntityRemove(MainUtil.setEntityInfo(tag, change.getEntity())); + LinCompoundTag tag = change.state.getNbt(); + assert tag != null; + addEntityRemove(FaweCompoundTag.of(NbtUtils.withEntityInfo(tag, change.getEntity()))); } @Override @@ -304,9 +360,9 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { public void add(BlockChange change) { try { - BlockVector3 loc = change.getPosition(); + BlockVector3 loc = change.position(); BaseBlock from = change.previous(); - BaseBlock to = change.getCurrent(); + BaseBlock to = change.current(); add(loc, from, to); } catch (Exception e) { LOGGER.catching(e); @@ -326,31 +382,28 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { public void add(int x, int y, int z, BaseBlock from, BaseBlock to) { try { - if (from.hasNbtData()) { - CompoundTag nbt = from.getNbtData(); - assert nbt != null; - addTileRemove(MainUtil.setPosition(nbt, x, y, z)); + LinCompoundTag nbt = from.getNbt(); + if (nbt != null) { + addTileRemove(FaweCompoundTag.of(NbtUtils.withPosition(nbt, x, y, z))); } - if (to.hasNbtData()) { - CompoundTag nbt = to.getNbtData(); - assert nbt != null; - addTileCreate(MainUtil.setPosition(nbt, x, y, z)); + nbt = to.getNbt(); + if (nbt != null) { + addTileCreate(FaweCompoundTag.of(NbtUtils.withPosition(nbt, x, y, z))); } int combinedFrom = from.getOrdinal(); int combinedTo = to.getOrdinal(); add(x, y, z, combinedFrom, combinedTo); } catch (Exception e) { - e.printStackTrace(); + LOGGER.catching(e); } } public void add(int x, int y, int z, int combinedFrom, BaseBlock to) { try { - if (to.hasNbtData()) { - CompoundTag nbt = to.getNbtData(); - assert nbt != null; - addTileCreate(MainUtil.setPosition(nbt, x, y, z)); + LinCompoundTag nbt = to.getNbt(); + if (nbt != null) { + addTileCreate(FaweCompoundTag.of(NbtUtils.withPosition(nbt, x, y, z))); } int combinedTo = to.getInternalId(); add(x, y, z, combinedFrom, combinedTo); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractDelegateChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractDelegateChangeSet.java index f3f0cdae4..e84888848 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractDelegateChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractDelegateChangeSet.java @@ -1,6 +1,6 @@ package com.fastasyncworldedit.core.history.changeset; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.inventory.BlockBag; @@ -46,26 +46,6 @@ public class AbstractDelegateChangeSet extends AbstractChangeSet { parent.flush(); } - @Override - public void addTileCreate(CompoundTag tag) { - parent.addTileCreate(tag); - } - - @Override - public void addTileRemove(CompoundTag tag) { - parent.addTileRemove(tag); - } - - @Override - public void addEntityRemove(CompoundTag tag) { - parent.addEntityRemove(tag); - } - - @Override - public void addEntityCreate(CompoundTag tag) { - parent.addEntityCreate(tag); - } - @Override public void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to) { parent.addBiomeChange(x, y, z, from, to); @@ -146,6 +126,26 @@ public class AbstractDelegateChangeSet extends AbstractChangeSet { return parent.forwardIterator(); } + @Override + public void addTileCreate(final FaweCompoundTag tag) { + parent.addTileCreate(tag); + } + + @Override + public void addTileRemove(final FaweCompoundTag tag) { + parent.addTileRemove(tag); + } + + @Override + public void addEntityRemove(final FaweCompoundTag tag) { + parent.addEntityRemove(tag); + } + + @Override + public void addEntityCreate(final FaweCompoundTag tag) { + parent.addEntityCreate(tag); + } + @Override public void close() throws IOException { parent.close(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/BlockBagChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/BlockBagChangeSet.java index e17a78765..8c65be084 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/BlockBagChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/BlockBagChangeSet.java @@ -1,8 +1,6 @@ package com.fastasyncworldedit.core.history.changeset; import com.fastasyncworldedit.core.FaweCache; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBagException; import com.sk89q.worldedit.extent.inventory.UnplaceableBlockException; @@ -109,13 +107,4 @@ public class BlockBagChangeSet extends AbstractDelegateChangeSet { super.add(x, y, z, combinedFrom, combinedTo); } - @Override - public void addTileCreate(CompoundTag nbt) { - if (nbt.containsKey("items")) { - Map> map = new HashMap<>(nbt.getValue()); - map.remove("items"); - } - super.addTileCreate(nbt); - } - } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java index 211a71303..613b8def8 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java @@ -10,6 +10,7 @@ import com.fastasyncworldedit.core.history.change.MutableTileChange; import com.fastasyncworldedit.core.internal.exception.FaweSmallEditUnsupportedException; import com.fastasyncworldedit.core.internal.io.FaweInputStream; import com.fastasyncworldedit.core.internal.io.FaweOutputStream; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.util.MainUtil; import com.fastasyncworldedit.core.util.MathMan; import com.sk89q.jnbt.CompoundTag; @@ -21,9 +22,12 @@ import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockTypes; +import org.enginehub.linbus.stream.LinBinaryIO; +import org.enginehub.linbus.tree.LinRootEntry; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.DataOutput; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; @@ -398,56 +402,44 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { } @Override - public void addTileCreate(CompoundTag tag) { - if (tag == null) { - return; - } + public void addTileCreate(final FaweCompoundTag tag) { blockSize++; try { - NBTOutputStream nbtos = getTileCreateOS(); - nbtos.writeTag(tag); + DataOutput nbtos = getTileCreateOS(); + LinBinaryIO.write(nbtos, new LinRootEntry("tile-create", tag.linTag())); } catch (IOException e) { e.printStackTrace(); } } @Override - public void addTileRemove(CompoundTag tag) { - if (tag == null) { - return; - } + public void addTileRemove(final FaweCompoundTag tag) { blockSize++; try { - NBTOutputStream nbtos = getTileRemoveOS(); - nbtos.writeTag(tag); + DataOutput nbtos = getTileRemoveOS(); + LinBinaryIO.write(nbtos, new LinRootEntry("tile-remove", tag.linTag())); } catch (IOException e) { e.printStackTrace(); } } @Override - public void addEntityRemove(CompoundTag tag) { - if (tag == null) { - return; - } + public void addEntityRemove(final FaweCompoundTag tag) { blockSize++; try { - NBTOutputStream nbtos = getEntityRemoveOS(); - nbtos.writeTag(tag); + DataOutput nbtos = getEntityRemoveOS(); + LinBinaryIO.write(nbtos, new LinRootEntry("entity-remove", tag.linTag())); } catch (IOException e) { e.printStackTrace(); } } @Override - public void addEntityCreate(CompoundTag tag) { - if (tag == null) { - return; - } + public void addEntityCreate(final FaweCompoundTag tag) { blockSize++; try { - NBTOutputStream nbtos = getEntityCreateOS(); - nbtos.writeTag(tag); + DataOutput nbtos = getEntityCreateOS(); + LinBinaryIO.write(nbtos, new LinRootEntry("entity-create", tag.linTag())); } catch (IOException e) { e.printStackTrace(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/NullChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/NullChangeSet.java index 2a60b3913..99711b6cc 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/NullChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/NullChangeSet.java @@ -1,6 +1,6 @@ package com.fastasyncworldedit.core.history.changeset; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.world.World; @@ -25,22 +25,22 @@ public class NullChangeSet extends AbstractChangeSet { } @Override - public final void addTileCreate(CompoundTag tag) { + public void addTileCreate(final FaweCompoundTag tag) { } @Override - public final void addTileRemove(CompoundTag tag) { + public void addTileRemove(final FaweCompoundTag tag) { } @Override - public final void addEntityRemove(CompoundTag tag) { + public void addEntityRemove(final FaweCompoundTag tag) { } @Override - public final void addEntityCreate(CompoundTag tag) { + public void addEntityCreate(final FaweCompoundTag tag) { } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/EagerFaweCompoundTag.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/EagerFaweCompoundTag.java new file mode 100644 index 000000000..c41d8db1d --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/EagerFaweCompoundTag.java @@ -0,0 +1,7 @@ +package com.fastasyncworldedit.core.nbt; + +import org.enginehub.linbus.tree.LinCompoundTag; + +record EagerFaweCompoundTag(LinCompoundTag linTag) implements FaweCompoundTag { + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/FaweCompoundTag.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/FaweCompoundTag.java new file mode 100644 index 000000000..a244f7964 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/FaweCompoundTag.java @@ -0,0 +1,44 @@ +package com.fastasyncworldedit.core.nbt; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.sk89q.worldedit.util.concurrency.LazyReference; +import org.enginehub.linbus.tree.LinCompoundTag; + +/** + * A wrapper around compound tags, potentially lazily transformed. + * @since TODO + */ +public sealed interface FaweCompoundTag permits EagerFaweCompoundTag, LazyFaweCompoundTag { + + /** + * {@return a lazy compound component backed by a lazy reference} + * @param lazyReference the lazy reference to the actual compound tag + */ + static FaweCompoundTag of(LazyReference lazyReference) { + return new LazyFaweCompoundTag(lazyReference::getValue); + } + + /** + * {@return a lazy compound component backed by a supplier} + * Invocations to the supplier are memoized. + * @param supplier the supplier for the actual compound tag + */ + static FaweCompoundTag of(Supplier supplier) { + return new LazyFaweCompoundTag(Suppliers.memoize(supplier)); + } + + /** + * {@return a direct reference tho the given compound tag} + * @param linCompoundTag the tag to wrap + */ + static FaweCompoundTag of(LinCompoundTag linCompoundTag) { + return new EagerFaweCompoundTag(linCompoundTag); + } + + /** + * {@return the underlying tag} + */ + LinCompoundTag linTag(); + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/LazyFaweCompoundTag.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/LazyFaweCompoundTag.java new file mode 100644 index 000000000..afd0e4e48 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/LazyFaweCompoundTag.java @@ -0,0 +1,14 @@ +package com.fastasyncworldedit.core.nbt; + +import org.enginehub.linbus.tree.LinCompoundTag; + +import java.util.function.Supplier; + +record LazyFaweCompoundTag(Supplier linTagSupplier) implements FaweCompoundTag { + + @Override + public LinCompoundTag linTag() { + return this.linTagSupplier().get(); + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java index ff6842c0a..b14b7b39d 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java @@ -3,6 +3,8 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.internal.io.FastByteArrayOutputStream; import com.fastasyncworldedit.core.internal.io.FaweOutputStream; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.util.collection.AdaptedMap; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.platform.Capability; @@ -12,10 +14,13 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.registry.BlockRegistry; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; +import java.util.Collection; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.IntStream; /** @@ -54,11 +59,38 @@ public interface IBlocks extends Trimable { BlockState getBlock(int x, int y, int z); - Map getTiles(); + @Deprecated(forRemoval = true, since = "TODO") + default Map getTiles() { + return AdaptedMap.immutable(tiles(), pos -> pos, IBlocks::toCompoundTag); + } - CompoundTag getTile(int x, int y, int z); + Map tiles(); - Set getEntities(); + @Deprecated(forRemoval = true, since = "TODO") + default CompoundTag getTile(int x, int y, int z) { + final FaweCompoundTag tile = tile(x, y, z); + if (tile == null) { + return null; + } + return toCompoundTag(tile); + } + + @SuppressWarnings({"deprecation"}) + private static @Nonnull CompoundTag toCompoundTag(FaweCompoundTag tile) { + return new CompoundTag(tile.linTag()); + } + + @Nullable + FaweCompoundTag tile(int x, int y, int z); + + @Deprecated(forRemoval = true, since = "TODO") + default Set getEntities() { + return entities().stream() + .map(IBlocks::toCompoundTag) + .collect(Collectors.toSet()); + } + + Collection entities(); BiomeType getBiomeType(int x, int y, int z); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkExtent.java index 534a96fac..615f5fb50 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkExtent.java @@ -1,11 +1,7 @@ package com.fastasyncworldedit.core.queue; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.DoubleTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.NBTUtils; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; @@ -16,6 +12,12 @@ import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinStringTag; +import org.enginehub.linbus.tree.LinTag; +import org.enginehub.linbus.tree.LinTagType; import java.util.ArrayList; import java.util.HashMap; @@ -39,9 +41,9 @@ public interface IChunkExtent extends Extent { } @Override - default boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + default boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { final IChunk chunk = getOrCreateChunk(x >> 4, z >> 4); - return chunk.setTile(x & 15, y, z & 15, tile); + return chunk.tile(x & 15, y, z & 15, tile); } @Override @@ -124,19 +126,19 @@ public interface IChunkExtent extends Extent { @Override default Entity createEntity(Location location, BaseEntity entity, UUID uuid) { final IChunk chunk = getOrCreateChunk(location.getBlockX() >> 4, location.getBlockZ() >> 4); - Map> map = new HashMap<>(entity.getNbtData().getValue()); //do not modify original entity data - map.put("Id", new StringTag(entity.getType().getName())); + Map> map = new HashMap<>(entity.getNbt().value()); //do not modify original entity data + map.put("Id", LinStringTag.of(entity.getType().getName())); //Set pos - List posList = new ArrayList<>(); - posList.add(new DoubleTag(location.x())); - posList.add(new DoubleTag(location.y())); - posList.add(new DoubleTag(location.z())); - map.put("Pos", new ListTag(DoubleTag.class, posList)); + List posList = new ArrayList<>(); + posList.add(LinDoubleTag.of(location.x())); + posList.add(LinDoubleTag.of(location.y())); + posList.add(LinDoubleTag.of(location.z())); + map.put("Pos", LinListTag.of(LinTagType.doubleTag(), posList)); - NBTUtils.addUUIDToMap(map, uuid); + NbtUtils.addUUIDToMap(map, uuid); - chunk.setEntity(new CompoundTag(map)); + chunk.entity(FaweCompoundTag.of(LinCompoundTag.of(map))); return new IChunkEntity(this, location, uuid, entity); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java index b2ac59cb2..1ead25284 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java @@ -1,6 +1,7 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.extent.InputExtent; import com.sk89q.worldedit.math.BlockVector3; @@ -46,7 +47,26 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent, ITileInput { > T call(IChunkSet set, Runnable finalize); - CompoundTag getEntity(UUID uuid); + @Deprecated(forRemoval = true, since = "TODO") + default CompoundTag getEntity(UUID uuid) { + final FaweCompoundTag entity = entity(uuid); + if (entity == null) { + return null; + } + return new CompoundTag(entity.linTag()); + } + + /** + * {@return the compound tag describing the entity with the given UUID, if any} + * @param uuid the uuid of the entity + */ + @Nullable FaweCompoundTag entity(UUID uuid); + + @Override + @Deprecated(forRemoval = true, since = "TODO") + default CompoundTag getTile(int x, int y, int z) { + return IBlocks.super.getTile(x, y, z); + } boolean isCreateCopy(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java index bc621e66a..13400f769 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java @@ -1,7 +1,9 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.OutputExtent; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.math.BlockVector3; @@ -36,7 +38,12 @@ public interface IChunkSet extends IBlocks, OutputExtent { boolean isEmpty(); @Override - boolean setTile(int x, int y, int z, CompoundTag tile); + @Deprecated(forRemoval = true, since = "TODO") + default boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + return tile(x, y, z, FaweCompoundTag.of(tile.toLinTag())); + } + + boolean tile(int x, int y, int z, FaweCompoundTag tag); @Override void setBlockLight(int x, int y, int z, int value); @@ -53,7 +60,12 @@ public interface IChunkSet extends IBlocks, OutputExtent { void setFullBright(int layer); - void setEntity(CompoundTag tag); + @Deprecated(forRemoval = true, since = "TODO") + default void setEntity(CompoundTag tag) { + entity(FaweCompoundTag.of(tag::toLinTag)); + } + + void entity(FaweCompoundTag tag); void removeEntity(UUID uuid); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/ITileInput.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/ITileInput.java index 5d0641c81..eb0503858 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/ITileInput.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/ITileInput.java @@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.queue; import com.sk89q.jnbt.CompoundTag; +@Deprecated(forRemoval = true, since = "TODO") public interface ITileInput { CompoundTag getTile(int x, int y, int z); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/BitSetBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/BitSetBlocks.java index ae976777c..76f2191ed 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/BitSetBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/BitSetBlocks.java @@ -2,9 +2,9 @@ package com.fastasyncworldedit.core.queue.implementation.blocks; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.util.collection.MemBlockSet; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockState; @@ -13,6 +13,7 @@ import com.sk89q.worldedit.world.block.BlockTypesCache; import javax.annotation.Nullable; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Set; @@ -74,7 +75,7 @@ public class BitSetBlocks implements IChunkSet { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) { + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) { return false; } @@ -107,7 +108,7 @@ public class BitSetBlocks implements IChunkSet { } @Override - public void setEntity(CompoundTag tag) { + public void entity(final FaweCompoundTag tag) { } @Override @@ -181,18 +182,18 @@ public class BitSetBlocks implements IChunkSet { } @Override - public Map getTiles() { + public Map tiles() { return Collections.emptyMap(); } @Override - public CompoundTag getTile(int x, int y, int z) { + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { return null; } @Override - public Set getEntities() { - return Collections.emptySet(); + public Collection entities() { + return Collections.emptyList(); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharGetBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharGetBlocks.java index 2c89a7108..cd1c1b76f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharGetBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharGetBlocks.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.core.queue.implementation.blocks; +import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.sk89q.worldedit.world.block.BaseBlock; @@ -20,7 +21,7 @@ public abstract class CharGetBlocks extends CharBlocks implements IChunkGet { @Override public BaseBlock getFullBlock(int x, int y, int z) { BlockState state = BlockTypesCache.states[get(x, y, z)]; - return state.toBaseBlock(this, x, y, z); + return state.toBaseBlock((IBlocks) this, x, y, z); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharSetBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharSetBlocks.java index da28e5925..8d7c059ed 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharSetBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharSetBlocks.java @@ -4,16 +4,18 @@ import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.math.BlockVector3ChunkMap; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.Pool; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypesCache; +import javax.annotation.Nullable; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.HashSet; @@ -36,8 +38,8 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { public BiomeType[][] biomes; public char[][] light; public char[][] skyLight; - public BlockVector3ChunkMap tiles; - public HashSet entities; + public BlockVector3ChunkMap tiles; + public HashSet entities; public HashSet entityRemoves; public EnumMap heightMaps; private boolean fastMode = false; @@ -71,17 +73,17 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { } @Override - public Map getTiles() { + public Map tiles() { return tiles == null ? Collections.emptyMap() : tiles; } @Override - public CompoundTag getTile(int x, int y, int z) { + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { return tiles == null ? null : tiles.get(x, y, z); } @Override - public Set getEntities() { + public Collection entities() { return entities == null ? Collections.emptySet() : entities; } @@ -132,12 +134,12 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) { + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) { if (tiles == null) { tiles = new BlockVector3ChunkMap<>(); } updateSectionIndexRange(y >> 4); - tiles.put(x, y, z, tile); + tiles.put(x, y, z, tag); return true; } @@ -259,7 +261,7 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { } @Override - public void setEntity(CompoundTag tag) { + public void entity(final FaweCompoundTag tag) { if (entities == null) { entities = new HashSet<>(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java index 042870666..273f44952 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java @@ -2,10 +2,10 @@ package com.fastasyncworldedit.core.queue.implementation.blocks; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; @@ -15,9 +15,9 @@ import com.sk89q.worldedit.world.block.BlockTypes; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collection; import java.util.Collections; import java.util.Map; -import java.util.Set; import java.util.UUID; import java.util.concurrent.Future; @@ -48,24 +48,19 @@ public final class NullChunkGet implements IChunkGet { return BlockTypes.AIR.getDefaultState(); } - @Nonnull - public Map getTiles() { + @Override + public Map tiles() { return Collections.emptyMap(); } - @Nullable - public CompoundTag getTile(int x, int y, int z) { + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { return null; } - @Nullable - public Set getEntities() { - return null; - } - - @Nullable - public CompoundTag getEntity(@Nonnull UUID uuid) { - return null; + @Override + public Collection entities() { + return Collections.emptyList(); } @Override @@ -123,6 +118,11 @@ public final class NullChunkGet implements IChunkGet { return null; } + @Override + public @Nullable FaweCompoundTag entity(final UUID uuid) { + return null; + } + @Nonnull public char[] load(int layer) { return FaweCache.INSTANCE.EMPTY_CHAR_4096; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ThreadUnsafeCharBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ThreadUnsafeCharBlocks.java index 90ae6b32e..c21e932a9 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ThreadUnsafeCharBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ThreadUnsafeCharBlocks.java @@ -4,9 +4,9 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.math.BlockVector3ChunkMap; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkSet; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; @@ -17,6 +17,7 @@ import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; @@ -44,8 +45,8 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { private BiomeType[][] biomes; private char[][] light; private char[][] skyLight; - private BlockVector3ChunkMap tiles; - private HashSet entities; + private BlockVector3ChunkMap tiles; + private HashSet entities; private HashSet entityRemoves; private Map heightMaps; private boolean fastMode; @@ -64,8 +65,8 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { int sectionCount, char[][] light, char[][] skyLight, - BlockVector3ChunkMap tiles, - HashSet entities, + BlockVector3ChunkMap tiles, + HashSet entities, HashSet entityRemoves, Map heightMaps, char defaultOrdinal, @@ -116,18 +117,18 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { } @Override - public Map getTiles() { + public Map tiles() { return tiles == null ? Collections.emptyMap() : tiles; } @Override - public CompoundTag getTile(int x, int y, int z) { + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { return tiles == null ? null : tiles.get(x, y, z); } @Override - public Set getEntities() { - return entities == null ? Collections.emptySet() : entities; + public Collection entities() { + return entities == null ? Collections.emptyList() : entities; } @Override @@ -268,12 +269,12 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) { + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) { updateSectionIndexRange(y >> 4); if (tiles == null) { tiles = new BlockVector3ChunkMap<>(); } - tiles.put(x, y, z, tile); + tiles.put(x, y, z, tag); return true; } @@ -358,7 +359,7 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { } @Override - public void setEntity(CompoundTag tag) { + public void entity(final FaweCompoundTag tag) { if (entities == null) { entities = new HashSet<>(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java index a7417eddf..7c36eb94c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java @@ -3,6 +3,7 @@ package com.fastasyncworldedit.core.queue.implementation.chunk; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; @@ -11,7 +12,6 @@ import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent; import com.fastasyncworldedit.core.util.MemUtil; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; @@ -22,6 +22,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; +import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -76,18 +77,8 @@ public class ChunkHolder> implements IQueueChunk { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tag) { - return delegate.set(this).setTile(x, y, z, tag); - } - - @Override - public CompoundTag getTile(int x, int y, int z) { - return delegate.set(this).getTile(x, y, z); - } - - @Override - public void setEntity(CompoundTag tag) { - delegate.set(this).setEntity(tag); + public void entity(final FaweCompoundTag tag) { + delegate.set(this).entity(tag); } @Override @@ -163,11 +154,6 @@ public class ChunkHolder> implements IQueueChunk { return isInit; } - @Override - public CompoundTag getEntity(UUID uuid) { - return delegate.get(this).getEntity(uuid); - } - @Override public int setCreateCopy(boolean createCopy) { this.createCopy = createCopy; @@ -879,16 +865,6 @@ public class ChunkHolder> implements IQueueChunk { } }; - @Override - public Map getTiles() { - return delegate.get(this).getTiles(); - } - - @Override - public Set getEntities() { - return delegate.get(this).getEntities(); - } - @Override public boolean hasSection(int layer) { return chunkExisting != null && chunkExisting.hasSection(layer); @@ -946,6 +922,11 @@ public class ChunkHolder> implements IQueueChunk { return chunkSet == null || chunkSet.isEmpty(); } + @Override + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) { + return false; + } + /** * Get or create the existing part of this chunk. */ @@ -1093,6 +1074,21 @@ public class ChunkHolder> implements IQueueChunk { return delegate.getBlock(this, x, y, z); } + @Override + public Map tiles() { + return delegate.get(this).tiles(); + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return delegate.get(this).tile(x, y, z); + } + + @Override + public Collection entities() { + return delegate.get(this).entities(); + } + @Override public BaseBlock getFullBlock(int x, int y, int z) { return delegate.getFullBlock(this, x, y, z); @@ -1158,6 +1154,11 @@ public class ChunkHolder> implements IQueueChunk { return delegate.getHeightMap(this, type); } + @Override + public @Nullable FaweCompoundTag entity(final UUID uuid) { + return delegate.get(this).entity(uuid); + } + public interface IBlockDelegate { > IChunkGet get(ChunkHolder chunk); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java index 8cc6471ba..14107e83a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java @@ -2,10 +2,10 @@ package com.fastasyncworldedit.core.queue.implementation.chunk; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IQueueChunk; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.biome.BiomeType; @@ -16,6 +16,7 @@ import com.sk89q.worldedit.world.block.BlockTypes; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Set; @@ -53,13 +54,11 @@ public final class NullChunk implements IQueueChunk { return false; } - public boolean setTile(int x, int y, int z, @Nonnull CompoundTag tag) { + @Override + public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tag) { return false; } - public void setEntity(@Nonnull CompoundTag tag) { - } - public void removeEntity(@Nonnull UUID uuid) { } @@ -112,6 +111,10 @@ public final class NullChunk implements IQueueChunk { public void setFullBright(int layer) { } + @Override + public void entity(final FaweCompoundTag tag) { + } + public void removeSectionLighting(int layer, boolean sky) { } @@ -147,25 +150,26 @@ public final class NullChunk implements IQueueChunk { return BlockTypes.__RESERVED__.getDefaultState(); } + @Override + public Map tiles() { + return Collections.emptyMap(); + } + + @Override + public @Nullable FaweCompoundTag tile(final int x, final int y, final int z) { + return null; + } + + @Override + public Collection entities() { + return Collections.emptyList(); + } + @Nonnull public BaseBlock getFullBlock(int x, int y, int z) { return BlockTypes.__RESERVED__.getDefaultState().toBaseBlock(); } - @Nonnull - public Map getTiles() { - return Collections.emptyMap(); - } - - @Nullable - public CompoundTag getTile(int x, int y, int z) { - return null; - } - - @Nonnull - public Set getEntities() { - return Collections.emptySet(); - } @Nullable public char[] load(int layer) { @@ -178,11 +182,6 @@ public final class NullChunk implements IQueueChunk { return null; } - @Nullable - public CompoundTag getEntity(@Nonnull UUID uuid) { - return null; - } - @Override public int setCreateCopy(boolean createCopy) { return -1; @@ -230,6 +229,11 @@ public final class NullChunk implements IQueueChunk { return null; } + @Override + public @Nullable FaweCompoundTag entity(final UUID uuid) { + return null; + } + public boolean trim(boolean aggressive) { return true; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java index 8ab673b77..115397788 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java @@ -34,6 +34,7 @@ import net.jpountz.lz4.LZ4Compressor; import net.jpountz.lz4.LZ4Factory; import net.jpountz.lz4.LZ4FastDecompressor; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -424,8 +425,10 @@ public class MainUtil { * @param y New Y coordinate * @param z New Z coordinate * @return New tag + * @deprecated use {@link NbtUtils#withPosition} instead */ @Nonnull + @Deprecated(forRemoval = true, since = "TODO") public static CompoundTag setPosition(@Nonnull CompoundTag tag, int x, int y, int z) { Map> value = new HashMap<>(tag.getValue()); value.put("x", new IntTag(x)); @@ -440,8 +443,10 @@ public class MainUtil { * @param tag Tag to copy * @param entity Entity * @return New tag + * @deprecated use {@link NbtUtils#withEntityInfo(LinCompoundTag, Entity)} instead */ @Nonnull + @Deprecated(forRemoval = true, since = "TODO") public static CompoundTag setEntityInfo(@Nonnull CompoundTag tag, @Nonnull Entity entity) { Map> map = new HashMap<>(tag.getValue()); map.put("Id", new StringTag(entity.getState().getType().id())); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java index 07157e820..07a752131 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java @@ -1,17 +1,29 @@ package com.fastasyncworldedit.core.util; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.storage.InvalidFormatException; import org.enginehub.linbus.tree.LinByteTag; import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinDoubleTag; +import org.enginehub.linbus.tree.LinIntArrayTag; import org.enginehub.linbus.tree.LinIntTag; +import org.enginehub.linbus.tree.LinListTag; +import org.enginehub.linbus.tree.LinLongTag; import org.enginehub.linbus.tree.LinShortTag; import org.enginehub.linbus.tree.LinTag; import org.enginehub.linbus.tree.LinTagType; +import javax.annotation.Nonnull; import java.util.HashMap; import java.util.Map; +import java.util.UUID; -public class NbtUtils { +public final class NbtUtils { + + private NbtUtils() { + } /** * Get child tag of a NBT structure. @@ -79,4 +91,124 @@ public class NbtUtils { return value; } + /** + * Tries to extract UUID information from a compound tag + * + * @param compoundTag the compound tag to extract uuid information from + * @return the extracted UUID + * @since TODO + */ + public static UUID uuid(FaweCompoundTag compoundTag) { + final LinCompoundTag linTag = compoundTag.linTag(); + { + final LinIntArrayTag uuidTag = linTag.findTag("UUID", LinTagType.intArrayTag()); + if (uuidTag != null) { + int[] arr = uuidTag.value(); + return new UUID((long) arr[0] << 32 | (arr[1] & 0xFFFFFFFFL), (long) arr[2] << 32 | (arr[3] & 0xFFFFFFFFL)); + } + } + { + final LinLongTag uuidMostTag = linTag.findTag("UUIDMost", LinTagType.longTag()); + if (uuidMostTag != null) { + return new UUID(uuidMostTag.valueAsLong(), linTag.getTag("UUIDLeast", LinTagType.longTag()).valueAsLong()); + } + } + { + final LinLongTag uuidMostTag = linTag.findTag("WorldUUIDMost", LinTagType.longTag()); + if (uuidMostTag != null) { + return new UUID(uuidMostTag.valueAsLong(), linTag.getTag("WorldUUIDLeast", LinTagType.longTag()).valueAsLong()); + } + + } + { + final LinLongTag uuidMostTag = linTag.findTag("PersistentIDMSB", LinTagType.longTag()); + if (uuidMostTag != null) { + return new UUID(uuidMostTag.valueAsLong(), linTag.getTag("PersistentIDLSB", LinTagType.longTag()).valueAsLong()); + } + + } + throw new IllegalArgumentException("no uuid present"); + + } + + /** + * Create a copy of the tag and modify the (x, y, z) coordinates + * + * @param tag Tag to copy + * @param x New X coordinate + * @param y New Y coordinate + * @param z New Z coordinate + * @return New tag + * @since TODO + */ + public static @Nonnull LinCompoundTag withPosition(@Nonnull LinCompoundTag tag, int x, int y, int z) { + return tag.toBuilder() + .putInt("x", x) + .putInt("y", y) + .putInt("z", z) + .build(); + } + + /** + * Create a copy of the tag and modify the (x, y, z) coordinates + * + * @param tag Tag to copy + * @param x New X coordinate + * @param y New Y coordinate + * @param z New Z coordinate + * @return New tag + * @since TODO + */ + public static @Nonnull FaweCompoundTag withPosition(@Nonnull FaweCompoundTag tag, int x, int y, int z) { + return FaweCompoundTag.of(withPosition(tag.linTag(), x, y, z)); + } + + /** + * {@return a copy of the given tag with the Id and the Pos of the given entity} + * + * @param tag the tag to copy + * @param entity the entity to use the Id and the Pos from + * @since TODO + */ + public static @Nonnull LinCompoundTag withEntityInfo(@Nonnull LinCompoundTag tag, @Nonnull Entity entity) { + final LinCompoundTag.Builder builder = tag.toBuilder() + .putString("Id", entity.getState().getType().id()); + LinListTag pos = tag.findListTag("Pos", LinTagType.doubleTag()); + if (pos != null) { // TODO why only if pos != null? + Location loc = entity.getLocation(); + final LinListTag newPos = LinListTag.builder(LinTagType.doubleTag()) + .add(LinDoubleTag.of(loc.x())) + .add(LinDoubleTag.of(loc.y())) + .add(LinDoubleTag.of(loc.z())) + .build(); + builder.put("Pos", newPos); + } + return builder.build(); + } + + /** + * Adds a UUID to the given map + * + * @param map the map to insert to + * @param uuid the uuid to insert + * @since TODO + */ + public static void addUUIDToMap(Map> map, UUID uuid) { + int[] uuidArray = new int[4]; + uuidArray[0] = (int) (uuid.getMostSignificantBits() >> 32); + uuidArray[1] = (int) uuid.getMostSignificantBits(); + uuidArray[2] = (int) (uuid.getLeastSignificantBits() >> 32); + uuidArray[3] = (int) uuid.getLeastSignificantBits(); + map.put("UUID", LinIntArrayTag.of(uuidArray)); + + map.put("UUIDMost", LinLongTag.of(uuid.getMostSignificantBits())); + map.put("UUIDLeast", LinLongTag.of(uuid.getLeastSignificantBits())); + + map.put("WorldUUIDMost", LinLongTag.of(uuid.getMostSignificantBits())); + map.put("WorldUUIDLeast", LinLongTag.of(uuid.getLeastSignificantBits())); + + map.put("PersistentIDMSB", LinLongTag.of(uuid.getMostSignificantBits())); + map.put("PersistentIDLSB", LinLongTag.of(uuid.getLeastSignificantBits())); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java index 4310d6523..481f8d54f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java @@ -1,5 +1,7 @@ package com.fastasyncworldedit.core.world.block; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.ITileInput; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -11,9 +13,21 @@ public enum CompoundInput { public BaseBlock get(BlockState state, ITileInput input, int x, int y, int z) { return state.toBaseBlock(input.getTile(x, y, z)); } + + @Override + public BaseBlock get(final BlockState state, final IBlocks blocks, final int x, final int y, final int z) { + final FaweCompoundTag tile = blocks.tile(x, y, z); + assert tile != null : "container without tile entity"; + return state.toBaseBlock(tile.linTag()); + } }; + @Deprecated(forRemoval = true, since = "TODO") public BaseBlock get(BlockState state, ITileInput input, int x, int y, int z) { return state.toBaseBlock(); } + + public BaseBlock get(BlockState state, IBlocks blocks, int x, int y, int z) { + return state.toBaseBlock(); + } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java index 05616a414..616e90b37 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.core.wrappers; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.fastasyncworldedit.core.util.ExtentTraverser; @@ -187,8 +188,8 @@ public class WorldWrapper extends AbstractWorld { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { - return parent.setTile(x, y, z, tile); + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { + return parent.tile(x, y, z, tile); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java index b742cb6f8..11143a6c7 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java @@ -172,7 +172,9 @@ public final class NBTUtils { * @param map Map to add uuid to * @param uuid {@link UUID} to add * @since 2.4.0 + * @deprecated use {@link com.fastasyncworldedit.core.util.NbtUtils#addUUIDToMap(Map, UUID)} instead */ + @Deprecated(forRemoval = true, since = "TODO") public static void addUUIDToMap(Map> map, UUID uuid) { int[] uuidArray = new int[4]; uuidArray[0] = (int) (uuid.getMostSignificantBits() >> 32); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java index f2d7dc884..267734247 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java @@ -25,6 +25,7 @@ import com.fastasyncworldedit.core.extent.HistoryExtent; import com.fastasyncworldedit.core.extent.NullExtent; import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet; import com.fastasyncworldedit.core.internal.exception.FaweException; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.util.ExtentTraverser; @@ -425,8 +426,8 @@ public class AbstractDelegateExtent implements Extent { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { - return setBlock(x, y, z, getBlock(x, y, z).toBaseBlock(tile)); + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { + return setBlock(x, y, z, getBlock(x, y, z).toBaseBlock(tile.linTag())); } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java index 1b4420d27..9f73c8f5e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java @@ -736,7 +736,6 @@ public interface Extent extends InputExtent, OutputExtent { default > int setBlocks(Region region, B block) throws MaxChangedBlocksException { checkNotNull(region); checkNotNull(block); - boolean hasNbt = block instanceof BaseBlock && block.hasNbtData(); int changes = 0; for (BlockVector3 pos : region) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/NullExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/NullExtent.java index 934b52204..b98e0f4b8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/NullExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/NullExtent.java @@ -19,8 +19,8 @@ package com.sk89q.worldedit.extent; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; @@ -108,7 +108,7 @@ public class NullExtent implements Extent { } @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { return false; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java index 9346bf380..1e988b51f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java @@ -21,6 +21,7 @@ package com.sk89q.worldedit.extent; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.math.MutableBlockVector3; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; @@ -68,7 +69,24 @@ public interface OutputExtent { return setBlock(MutableBlockVector3.get(x, y, z), block); } - boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException; + /** + * @deprecated use {@link #tile(int, int, int, FaweCompoundTag)} instead + */ + @Deprecated(forRemoval = true, since = "TODO") + default boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + return tile(x, y, z, FaweCompoundTag.of(tile.toLinTag())); + } + + /** + * Sets a tile/block entity at the given location. + * @param x the x position + * @param y the y position + * @param z the z position + * @param tile the tile/block entity to set + * @return {@code true} if the tile/block entity was placed + * @since TODO + */ + boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException; /** * Check if this extent fully supports 3D biomes. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java index cf4623739..e67c28abf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java @@ -23,6 +23,7 @@ import com.fastasyncworldedit.core.extent.clipboard.SimpleClipboard; import com.fastasyncworldedit.core.function.visitor.Order; import com.fastasyncworldedit.core.math.MutableBlockVector2; import com.fastasyncworldedit.core.math.OffsetBlockVector3; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.google.common.collect.Iterators; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; @@ -200,16 +201,17 @@ public class BlockArrayClipboard implements Clipboard { //FAWE start @Override - public boolean setTile(int x, int y, int z, CompoundTag tag) { + public boolean tile(int x, int y, int z, FaweCompoundTag tag) { x -= offset.x(); y -= offset.y(); z -= offset.z(); - return getParent().setTile(x, y, z, tag); + return getParent().tile(x, y, z, tag); } + @Deprecated(forRemoval = true, since = "TODO") public boolean setTile(BlockVector3 position, CompoundTag tag) { - return setTile(position.x(), position.y(), position.z(), tag); + return tile(position.x(), position.y(), position.z(), FaweCompoundTag.of(tag.toLinTag())); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java index ee2789a33..d8dc989da 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java @@ -852,6 +852,7 @@ public abstract class BlockVector3 { return orDefault.getBiome(this); } + @Deprecated(forRemoval = true, since = "TODO") public CompoundTag getNbtData(Extent orDefault) { return orDefault.getFullBlock(x(), y(), z()).getNbtData(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/RequestExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/RequestExtent.java index 2af8232af..5aedae6d9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/RequestExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/RequestExtent.java @@ -19,7 +19,7 @@ package com.sk89q.worldedit.session.request; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; @@ -119,8 +119,8 @@ public class RequestExtent implements Extent { //FAWE start @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { - return getExtent().setTile(x, y, z, tile); + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { + return getExtent().tile(x, y, z, tile); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java index 0e962d746..d3ad7bfd9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java @@ -19,11 +19,11 @@ package com.sk89q.worldedit.world; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.blocks.NullChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.google.common.collect.ImmutableSet; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; @@ -204,7 +204,7 @@ public class NullWorld extends AbstractWorld { //FAWE start @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { return false; } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java index ab93a4016..ea54b1c7a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BaseBlock.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.world.block; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.registry.state.PropertyKey; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; @@ -262,15 +263,15 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { @Override public void applyTileEntity(OutputExtent output, int x, int y, int z) { - CompoundTag nbt = getNbtData(); + LinCompoundTag nbt = getNbt(); if (nbt != null) { - output.setTile(x, y, z, nbt); + output.tile(x, y, z, FaweCompoundTag.of(nbt)); } } @Override public BaseBlock withPropertyId(int propertyId) { - return getBlockType().withPropertyId(propertyId).toBaseBlock(getNbtData()); + return getBlockType().withPropertyId(propertyId).toBaseBlock(getNbtReference()); } @Override @@ -285,7 +286,7 @@ public class BaseBlock implements BlockStateHolder, TileEntityBlock { @Override public BaseBlock with(PropertyKey property, V value) { - return toImmutableState().with(property, value).toBaseBlock(getNbtData()); + return toImmutableState().with(property, value).toBaseBlock(getNbtReference()); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java index caa8ba919..824ad2b85 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java @@ -22,6 +22,7 @@ package com.sk89q.worldedit.world.block; import com.fastasyncworldedit.core.command.SuggestInputParseException; import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.function.mask.SingleBlockStateMask; +import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.ITileInput; import com.fastasyncworldedit.core.registry.state.PropertyKey; import com.fastasyncworldedit.core.util.MutableCharSequence; @@ -476,6 +477,12 @@ public class BlockState implements BlockStateHolder, Pattern { public BaseBlock toBaseBlock(ITileInput input, int x, int y, int z) { return compoundInput.get(this, input, x, y, z); } + + @Override + public BaseBlock toBaseBlock(final IBlocks blocks, final int x, final int y, final int z) { + return compoundInput.get(this, blocks, x, y, z); + } + //FAWE end @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java index f2ea08b67..808f8f23f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockStateHolder.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.world.block; +import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.ITileInput; import com.fastasyncworldedit.core.registry.state.PropertyKey; import com.sk89q.jnbt.CompoundTag; @@ -201,6 +202,10 @@ public interface BlockStateHolder> extends TileEnt default BaseBlock toBaseBlock(ITileInput input, int x, int y, int z) { throw new UnsupportedOperationException("State is immutable"); } + + default BaseBlock toBaseBlock(IBlocks blocks, int x, int y, int z) { + throw new UnsupportedOperationException("State is immutable"); + } //FAWE end default String getAsString() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java index c8baea757..d37929a37 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.world.registry; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import javax.annotation.Nullable; @@ -185,7 +186,19 @@ public interface BlockMaterial { * @return default tile entity data */ @Nullable - CompoundTag getDefaultTile(); + default CompoundTag getDefaultTile() { + final FaweCompoundTag faweCompoundTag = defaultTile(); + if (faweCompoundTag == null) { + return null; + } + return new CompoundTag(faweCompoundTag.linTag()); + } + + /** + * {@return the default tile associated with this material, if any} + * @since TODO + */ + @Nullable FaweCompoundTag defaultTile(); /** * Get the map color. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughBlockMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughBlockMaterial.java index 95743b80a..28b09a30e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughBlockMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/PassthroughBlockMaterial.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.world.registry; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; import javax.annotation.Nullable; @@ -168,5 +169,11 @@ public class PassthroughBlockMaterial implements BlockMaterial { public CompoundTag getDefaultTile() { return blockMaterial.getDefaultTile(); } + + @Override + public @Nullable FaweCompoundTag defaultTile() { + return blockMaterial.defaultTile(); + } + //FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleBlockMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleBlockMaterial.java index 763ac81bc..737510816 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleBlockMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/SimpleBlockMaterial.java @@ -19,8 +19,11 @@ package com.sk89q.worldedit.world.registry; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.jnbt.CompoundTag; +import javax.annotation.Nullable; + class SimpleBlockMaterial implements BlockMaterial { private boolean isAir; @@ -251,8 +254,12 @@ class SimpleBlockMaterial implements BlockMaterial { } @Override - public CompoundTag getDefaultTile() { - return tile; + public @Nullable FaweCompoundTag defaultTile() { + // this implementation is very lazy, but SimpleBlockMaterial isn't really used anyway + if (tile != null) { + return FaweCompoundTag.of(tile.toLinTag()); + } + return null; } //FAWE end From e8c7d67b5b960dcc1fe60c4e41104141905b6a40 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sat, 14 Sep 2024 10:48:59 +0200 Subject: [PATCH 24/59] Fix regen on modern versions (#2881) * work on regen * simplify * fix more regen * cleanup, backport * revert unneeded change --- .../fawe/v1_20_R2/regen/PaperweightRegen.java | 412 +++------------ .../fawe/v1_20_R3/regen/PaperweightRegen.java | 411 +++------------ .../fawe/v1_20_R4/regen/PaperweightRegen.java | 386 ++------------ .../fawe/v1_21_R1/PaperweightFaweAdapter.java | 3 +- .../fawe/v1_21_R1/regen/PaperweightRegen.java | 413 ++------------- .../bukkit/adapter/Regenerator.java | 496 +----------------- 6 files changed, 234 insertions(+), 1887 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/regen/PaperweightRegen.java index 2ec8e6e41..e892c6f7e 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/regen/PaperweightRegen.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/regen/PaperweightRegen.java @@ -4,167 +4,74 @@ import com.fastasyncworldedit.bukkit.adapter.Regenerator; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.queue.IChunkCache; import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.util.ReflectionUtils; -import com.fastasyncworldedit.core.util.TaskManager; +import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkCache; import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Either; import com.mojang.serialization.Lifecycle; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.PaperweightGetBlocks; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.io.file.SafeFiles; import com.sk89q.worldedit.world.RegenOptions; -import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message; -import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ThreadedLevelLightEngine; import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.thread.ProcessorHandle; -import net.minecraft.util.thread.ProcessorMailbox; +import net.minecraft.util.ProgressListener; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.LevelSettings; import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.FixedBiomeSource; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.UpgradeData; import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.WorldOptions; -import net.minecraft.world.level.levelgen.blending.BlendingData; -import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; -import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.PrimaryLevelData; -import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; -import org.bukkit.Chunk; +import org.bukkit.World; import org.bukkit.craftbukkit.v1_20_R2.CraftServer; import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_20_R2.generator.CustomChunkGenerator; import org.bukkit.generator.BiomeProvider; -import org.bukkit.generator.BlockPopulator; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.lang.reflect.Field; import java.nio.file.Path; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.OptionalLong; -import java.util.Random; -import java.util.concurrent.CompletableFuture; import java.util.function.BooleanSupplier; import java.util.function.Supplier; import static net.minecraft.core.registries.Registries.BIOME; -public class PaperweightRegen extends Regenerator { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); +public class PaperweightRegen extends Regenerator { private static final Field serverWorldsField; private static final Field paperConfigField; - private static final Field flatBedrockField; - private static final Field generatorSettingFlatField; private static final Field generatorSettingBaseSupplierField; - private static final Field delegateField; - private static final Field chunkSourceField; - private static final Field generatorStructureStateField; - private static final Field ringPositionsField; - private static final Field hasGeneratedPositionsField; - //list of chunk stati in correct order without FULL - private static final Map chunkStati = new LinkedHashMap<>(); static { - chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing - chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps - chunkStati.put( - ChunkStatus.STRUCTURE_REFERENCES, - Concurrency.FULL - ); // structure refs: radius 8, but only writes to current chunk - chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0 - chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8 - chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE - chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results - /*chunkStati.put( - ChunkStatus.LIQUID_CARVERS, - Concurrency.NONE - ); // liquid carvers: radius 0, but RADIUS and FULL change results*/ - chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps - chunkStati.put( - ChunkStatus.LIGHT, - Concurrency.FULL - ); // light: radius 1, but no writes to other chunks, only current chunk - chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0 - // chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0 - try { serverWorldsField = CraftServer.class.getDeclaredField("worlds"); serverWorldsField.setAccessible(true); Field tmpPaperConfigField; - Field tmpFlatBedrockField; try { //only present on paper tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); tmpPaperConfigField.setAccessible(true); - - tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock"); - tmpFlatBedrockField.setAccessible(true); } catch (Exception e) { tmpPaperConfigField = null; - tmpFlatBedrockField = null; } paperConfigField = tmpPaperConfigField; - flatBedrockField = tmpFlatBedrockField; generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( "settings", "e")); generatorSettingBaseSupplierField.setAccessible(true); - - generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "d")); - generatorSettingFlatField.setAccessible(true); - - delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); - delegateField.setAccessible(true); - - chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "I")); - chunkSourceField.setAccessible(true); - - generatorStructureStateField = ChunkMap.class.getDeclaredField(Refraction.pickName("chunkGeneratorState", "v")); - generatorStructureStateField.setAccessible(true); - - ringPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(Refraction.pickName("ringPositions", "g")); - ringPositionsField.setAccessible(true); - - hasGeneratedPositionsField = ChunkGeneratorStructureState.class.getDeclaredField( - Refraction.pickName("hasGeneratedPositions", "h") - ); - hasGeneratedPositionsField.setAccessible(true); } catch (Exception e) { throw new RuntimeException(e); } @@ -172,43 +79,37 @@ public class PaperweightRegen extends Regenerator super.chunkStatuses.put(new ChunkStatusWrap(s), c)); - return true; } @Override - @SuppressWarnings("unchecked") protected boolean initNewWorld() throws Exception { //world folder tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); @@ -254,8 +155,10 @@ public class PaperweightRegen extends Regenerator getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { + public @NotNull Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { if (options.hasBiomeType()) { return singleBiome; } - return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome( - biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler() - ); + return super.getUncachedNoiseBiome(biomeX, biomeY, biomeZ); + } + + @Override + public void save( + @org.jetbrains.annotations.Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled + ) { + // noop, spigot + } + + @Override + public void save( + @Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled, + final boolean close + ) { + // noop, paper } }).get(); freshWorld.noSave = true; @@ -292,89 +208,6 @@ public class PaperweightRegen extends Regenerator generatorSettingBaseSupplier = (Holder) generatorSettingBaseSupplierField.get( - originalGenerator); - BiomeSource biomeSource; - if (options.hasBiomeType()) { - - biomeSource = new FixedBiomeSource( - DedicatedServer.getServer().registryAccess() - .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) - ); - } else { - biomeSource = originalGenerator.getBiomeSource(); - } - chunkGenerator = new NoiseBasedChunkGenerator( - biomeSource, - generatorSettingBaseSupplier - ); - } else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) { - chunkGenerator = customChunkGenerator.getDelegate(); - } else { - LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName()); - return false; - } - if (generator != null) { - chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); - generateConcurrent = generator.isParallelCapable(); - } -// chunkGenerator.conf = freshWorld.spigotConfig; - Does not exist anymore, may need to be re-addressed - - freshChunkProvider = new ServerChunkCache( - freshWorld, - session, - server.getFixerUpper(), - server.getStructureManager(), - server.executor, - chunkGenerator, - freshWorld.spigotConfig.viewDistance, - freshWorld.spigotConfig.simulationDistance, - server.forceSynchronousWrites(), - new RegenNoOpWorldLoadListener(), - (chunkCoordIntPair, state) -> { - }, - () -> server.overworld().getDataStorage() - ) { - // redirect to LevelChunks created in #createChunks - @Override - public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) { - ChunkAccess chunkAccess = getChunkAt(x, z); - if (chunkAccess == null && create) { - chunkAccess = createChunk(getProtoChunkAt(x, z)); - } - return chunkAccess; - } - }; - - if (seed == originalOpts.seed() && !options.hasBiomeType()) { - // Optimisation for needless ring position calculation when the seed and biome is the same. - ChunkGeneratorStructureState state = (ChunkGeneratorStructureState) generatorStructureStateField.get(originalChunkProvider.chunkMap); - boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(state); - if (hasGeneratedPositions) { - Map>> origPositions = - (Map>>) ringPositionsField.get(state); - Map>> copy = new Object2ObjectArrayMap<>( - origPositions); - ChunkGeneratorStructureState newState = (ChunkGeneratorStructureState) generatorStructureStateField.get(freshChunkProvider.chunkMap); - ringPositionsField.set(newState, copy); - hasGeneratedPositionsField.setBoolean(newState, true); - } - } - - - chunkSourceField.set(freshWorld, freshChunkProvider); - //let's start then - structureTemplateManager = server.getStructureManager(); - threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider); - return true; } @@ -389,7 +222,8 @@ public class PaperweightRegen extends Regenerator { try { - freshChunkProvider.close(false); + freshWorld.getChunkSource().getDataStorage().cache.clear(); + freshWorld.getChunkSource().close(false); } catch (Exception e) { throw new RuntimeException(e); } @@ -410,63 +244,20 @@ public class PaperweightRegen extends Regenerator getBlockPopulators() { - return originalServerWorld.getWorld().getPopulators(); - } - - @Override - protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { - // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> { - final CraftWorld world = freshWorld.getWorld(); - final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ); - blockPopulator.populate(world, random, chunk); - }); - } - @Override protected IChunkCache initSourceQueueCache() { - return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) { - @Override - public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) { - return getChunkAt(x, z); - } - }; + return new ChunkCache<>(BukkitAdapter.adapt(freshWorld.getWorld())); } //util @SuppressWarnings("unchecked") private void removeWorldFromWorldsMap() { - Fawe.instance().getQueueHandler().sync(() -> { - try { - Map map = (Map) serverWorldsField.get(Bukkit.getServer()); - map.remove("faweregentempworld"); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - }); + try { + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); + map.remove("faweregentempworld"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } } private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { @@ -483,11 +274,15 @@ public class PaperweightRegen extends Regenerator biomeRegistry, - @Nullable final BlendingData blendingData - ) { - super(pos, upgradeData, world, biomeRegistry, blendingData); - } - - // avoid warning on paper - - // compatibility with spigot - - public boolean generateFlatBedrock() { - return generateFlatBedrock; - } - - // no one will ever see the entities! - @Override - public List getEntities() { - return Collections.emptyList(); - } - - } - - protected class ChunkStatusWrap extends ChunkStatusWrapper { - - private final ChunkStatus chunkStatus; - - public ChunkStatusWrap(ChunkStatus chunkStatus) { - this.chunkStatus = chunkStatus; - } - - @Override - public int requiredNeighborChunkRadius() { - return chunkStatus.getRange(); - } - - @Override - public String name() { - return chunkStatus.toString(); - } - - @Override - public CompletableFuture processChunk(List accessibleChunks) { - return chunkStatus.generate( - Runnable::run, // TODO revisit, we might profit from this somehow? - freshWorld, - chunkGenerator, - structureTemplateManager, - threadedLevelLightEngine, - c -> CompletableFuture.completedFuture(Either.left(c)), - accessibleChunks - ); - } - - } - - /** - * A light engine that does nothing. As light is calculated after pasting anyway, we can avoid - * work this way. - */ - static class NoOpLightEngine extends ThreadedLevelLightEngine { - - private static final ProcessorMailbox MAILBOX = ProcessorMailbox.create(task -> { - }, "fawe-no-op"); - private static final ProcessorHandle> HANDLE = ProcessorHandle.of("fawe-no-op", m -> { - }); - - public NoOpLightEngine(final ServerChunkCache chunkProvider) { - super(chunkProvider, chunkProvider.chunkMap, false, MAILBOX, HANDLE); - } - - @Override - public CompletableFuture lightChunk(final ChunkAccess chunk, final boolean excludeBlocks) { - return CompletableFuture.completedFuture(chunk); - } - - } - } diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/regen/PaperweightRegen.java index edf9e9f90..cce14ee1c 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/regen/PaperweightRegen.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/regen/PaperweightRegen.java @@ -4,166 +4,74 @@ import com.fastasyncworldedit.bukkit.adapter.Regenerator; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.queue.IChunkCache; import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.util.TaskManager; +import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkCache; import com.google.common.collect.ImmutableList; -import com.mojang.datafixers.util.Either; import com.mojang.serialization.Lifecycle; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.PaperweightGetBlocks; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.io.file.SafeFiles; import com.sk89q.worldedit.world.RegenOptions; -import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message; -import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ThreadedLevelLightEngine; import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.thread.ProcessorHandle; -import net.minecraft.util.thread.ProcessorMailbox; +import net.minecraft.util.ProgressListener; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.LevelSettings; import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.FixedBiomeSource; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; import net.minecraft.world.level.chunk.ChunkStatus; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.UpgradeData; import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.WorldOptions; -import net.minecraft.world.level.levelgen.blending.BlendingData; -import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; -import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.PrimaryLevelData; -import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; -import org.bukkit.Chunk; +import org.bukkit.World; import org.bukkit.craftbukkit.v1_20_R3.CraftServer; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; -import org.bukkit.craftbukkit.v1_20_R3.generator.CustomChunkGenerator; import org.bukkit.generator.BiomeProvider; -import org.bukkit.generator.BlockPopulator; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.lang.reflect.Field; import java.nio.file.Path; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.OptionalLong; -import java.util.Random; -import java.util.concurrent.CompletableFuture; import java.util.function.BooleanSupplier; import java.util.function.Supplier; import static net.minecraft.core.registries.Registries.BIOME; -public class PaperweightRegen extends Regenerator { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); +public class PaperweightRegen extends Regenerator { private static final Field serverWorldsField; private static final Field paperConfigField; - private static final Field flatBedrockField; - private static final Field generatorSettingFlatField; private static final Field generatorSettingBaseSupplierField; - private static final Field delegateField; - private static final Field chunkSourceField; - private static final Field generatorStructureStateField; - private static final Field ringPositionsField; - private static final Field hasGeneratedPositionsField; - //list of chunk stati in correct order without FULL - private static final Map chunkStati = new LinkedHashMap<>(); static { - chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing - chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps - chunkStati.put( - ChunkStatus.STRUCTURE_REFERENCES, - Concurrency.FULL - ); // structure refs: radius 8, but only writes to current chunk - chunkStati.put(ChunkStatus.BIOMES, Concurrency.FULL); // biomes: radius 0 - chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8 - chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE - chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results - /*chunkStati.put( - ChunkStatus.LIQUID_CARVERS, - Concurrency.NONE - ); // liquid carvers: radius 0, but RADIUS and FULL change results*/ - chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps - chunkStati.put( - ChunkStatus.LIGHT, - Concurrency.FULL - ); // light: radius 1, but no writes to other chunks, only current chunk - chunkStati.put(ChunkStatus.SPAWN, Concurrency.FULL); // spawn: radius 0 - // chunkStati.put(ChunkStatus.HEIGHTMAPS, Concurrency.FULL); // heightmaps: radius 0 - try { serverWorldsField = CraftServer.class.getDeclaredField("worlds"); serverWorldsField.setAccessible(true); Field tmpPaperConfigField; - Field tmpFlatBedrockField; try { //only present on paper tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); tmpPaperConfigField.setAccessible(true); - - tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock"); - tmpFlatBedrockField.setAccessible(true); } catch (Exception e) { tmpPaperConfigField = null; - tmpFlatBedrockField = null; } paperConfigField = tmpPaperConfigField; - flatBedrockField = tmpFlatBedrockField; generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( "settings", "e")); generatorSettingBaseSupplierField.setAccessible(true); - - generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "d")); - generatorSettingFlatField.setAccessible(true); - - delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); - delegateField.setAccessible(true); - - chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "I")); - chunkSourceField.setAccessible(true); - - generatorStructureStateField = ChunkMap.class.getDeclaredField(Refraction.pickName("chunkGeneratorState", "v")); - generatorStructureStateField.setAccessible(true); - - ringPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(Refraction.pickName("ringPositions", "g")); - ringPositionsField.setAccessible(true); - - hasGeneratedPositionsField = ChunkGeneratorStructureState.class.getDeclaredField( - Refraction.pickName("hasGeneratedPositions", "h") - ); - hasGeneratedPositionsField.setAccessible(true); } catch (Exception e) { throw new RuntimeException(e); } @@ -171,43 +79,37 @@ public class PaperweightRegen extends Regenerator super.chunkStatuses.put(new ChunkStatusWrap(s), c)); - return true; } @Override - @SuppressWarnings("unchecked") protected boolean initNewWorld() throws Exception { //world folder tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); @@ -253,8 +155,10 @@ public class PaperweightRegen extends Regenerator getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { + public @NotNull Holder getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { if (options.hasBiomeType()) { return singleBiome; } - return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome( - biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler() - ); + return super.getUncachedNoiseBiome(biomeX, biomeY, biomeZ); + } + + @Override + public void save( + @org.jetbrains.annotations.Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled + ) { + // noop, spigot + } + + @Override + public void save( + @Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled, + final boolean close + ) { + // noop, paper } }).get(); freshWorld.noSave = true; @@ -291,89 +208,6 @@ public class PaperweightRegen extends Regenerator generatorSettingBaseSupplier = (Holder) generatorSettingBaseSupplierField.get( - originalGenerator); - BiomeSource biomeSource; - if (options.hasBiomeType()) { - - biomeSource = new FixedBiomeSource( - DedicatedServer.getServer().registryAccess() - .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) - ); - } else { - biomeSource = originalGenerator.getBiomeSource(); - } - chunkGenerator = new NoiseBasedChunkGenerator( - biomeSource, - generatorSettingBaseSupplier - ); - } else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) { - chunkGenerator = customChunkGenerator.getDelegate(); - } else { - LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName()); - return false; - } - if (generator != null) { - chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); - generateConcurrent = generator.isParallelCapable(); - } -// chunkGenerator.conf = freshWorld.spigotConfig; - Does not exist anymore, may need to be re-addressed - - freshChunkProvider = new ServerChunkCache( - freshWorld, - session, - server.getFixerUpper(), - server.getStructureManager(), - server.executor, - chunkGenerator, - freshWorld.spigotConfig.viewDistance, - freshWorld.spigotConfig.simulationDistance, - server.forceSynchronousWrites(), - new RegenNoOpWorldLoadListener(), - (chunkCoordIntPair, state) -> { - }, - () -> server.overworld().getDataStorage() - ) { - // redirect to LevelChunks created in #createChunks - @Override - public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean create) { - ChunkAccess chunkAccess = getChunkAt(x, z); - if (chunkAccess == null && create) { - chunkAccess = createChunk(getProtoChunkAt(x, z)); - } - return chunkAccess; - } - }; - - if (seed == originalOpts.seed() && !options.hasBiomeType()) { - // Optimisation for needless ring position calculation when the seed and biome is the same. - ChunkGeneratorStructureState state = (ChunkGeneratorStructureState) generatorStructureStateField.get(originalChunkProvider.chunkMap); - boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(state); - if (hasGeneratedPositions) { - Map>> origPositions = - (Map>>) ringPositionsField.get(state); - Map>> copy = new Object2ObjectArrayMap<>( - origPositions); - ChunkGeneratorStructureState newState = (ChunkGeneratorStructureState) generatorStructureStateField.get(freshChunkProvider.chunkMap); - ringPositionsField.set(newState, copy); - hasGeneratedPositionsField.setBoolean(newState, true); - } - } - - - chunkSourceField.set(freshWorld, freshChunkProvider); - //let's start then - structureTemplateManager = server.getStructureManager(); - threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider); - return true; } @@ -388,7 +222,8 @@ public class PaperweightRegen extends Regenerator { try { - freshChunkProvider.close(false); + freshWorld.getChunkSource().getDataStorage().cache.clear(); + freshWorld.getChunkSource().close(false); } catch (Exception e) { throw new RuntimeException(e); } @@ -409,63 +244,20 @@ public class PaperweightRegen extends Regenerator getBlockPopulators() { - return originalServerWorld.getWorld().getPopulators(); - } - - @Override - protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { - // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> { - final CraftWorld world = freshWorld.getWorld(); - final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ); - blockPopulator.populate(world, random, chunk); - }); - } - @Override protected IChunkCache initSourceQueueCache() { - return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) { - @Override - public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) { - return getChunkAt(x, z); - } - }; + return new ChunkCache<>(BukkitAdapter.adapt(freshWorld.getWorld())); } //util @SuppressWarnings("unchecked") private void removeWorldFromWorldsMap() { - Fawe.instance().getQueueHandler().sync(() -> { - try { - Map map = (Map) serverWorldsField.get(Bukkit.getServer()); - map.remove("faweregentempworld"); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - }); + try { + Map map = (Map) serverWorldsField.get(Bukkit.getServer()); + map.remove("faweregentempworld"); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } } private ResourceKey getWorldDimKey(org.bukkit.World.Environment env) { @@ -482,11 +274,15 @@ public class PaperweightRegen extends Regenerator biomeRegistry, - @Nullable final BlendingData blendingData - ) { - super(pos, upgradeData, world, biomeRegistry, blendingData); - } - - // avoid warning on paper - - // compatibility with spigot - - public boolean generateFlatBedrock() { - return generateFlatBedrock; - } - - // no one will ever see the entities! - @Override - public List getEntities() { - return Collections.emptyList(); - } - - } - - protected class ChunkStatusWrap extends ChunkStatusWrapper { - - private final ChunkStatus chunkStatus; - - public ChunkStatusWrap(ChunkStatus chunkStatus) { - this.chunkStatus = chunkStatus; - } - - @Override - public int requiredNeighborChunkRadius() { - return chunkStatus.getRange(); - } - - @Override - public String name() { - return chunkStatus.toString(); - } - - @Override - public CompletableFuture processChunk(List accessibleChunks) { - return chunkStatus.generate( - Runnable::run, // TODO revisit, we might profit from this somehow? - freshWorld, - chunkGenerator, - structureTemplateManager, - threadedLevelLightEngine, - c -> CompletableFuture.completedFuture(Either.left(c)), - accessibleChunks - ); - } - - } - - /** - * A light engine that does nothing. As light is calculated after pasting anyway, we can avoid - * work this way. - */ - static class NoOpLightEngine extends ThreadedLevelLightEngine { - - private static final ProcessorMailbox MAILBOX = ProcessorMailbox.create(task -> { - }, "fawe-no-op"); - private static final ProcessorHandle> HANDLE = ProcessorHandle.of("fawe-no-op", m -> { - }); - - public NoOpLightEngine(final ServerChunkCache chunkProvider) { - super(chunkProvider, chunkProvider.chunkMap, false, MAILBOX, HANDLE); - } - - @Override - public CompletableFuture lightChunk(final ChunkAccess chunk, final boolean excludeBlocks) { - return CompletableFuture.completedFuture(chunk); - } - - } - } diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/regen/PaperweightRegen.java index e21e7eef7..d80d098ff 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/regen/PaperweightRegen.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/regen/PaperweightRegen.java @@ -4,166 +4,73 @@ import com.fastasyncworldedit.bukkit.adapter.Regenerator; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.queue.IChunkCache; import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.util.TaskManager; +import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkCache; import com.google.common.collect.ImmutableList; import com.mojang.serialization.Lifecycle; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.Refraction; -import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4.PaperweightGetBlocks; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.io.file.SafeFiles; import com.sk89q.worldedit.world.RegenOptions; -import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.dedicated.DedicatedServer; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ChunkTaskPriorityQueueSorter.Message; -import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ThreadedLevelLightEngine; import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.util.thread.ProcessorHandle; -import net.minecraft.util.thread.ProcessorMailbox; +import net.minecraft.util.ProgressListener; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.LevelSettings; import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.biome.BiomeSource; -import net.minecraft.world.level.biome.FixedBiomeSource; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkGenerator; -import net.minecraft.world.level.chunk.ChunkGeneratorStructureState; -import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.UpgradeData; -import net.minecraft.world.level.chunk.status.ChunkStatus; -import net.minecraft.world.level.chunk.status.WorldGenContext; import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.FlatLevelSource; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; -import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.WorldOptions; -import net.minecraft.world.level.levelgen.blending.BlendingData; -import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; -import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.PrimaryLevelData; -import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; -import org.bukkit.Chunk; +import org.bukkit.World; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.generator.CustomChunkGenerator; import org.bukkit.generator.BiomeProvider; -import org.bukkit.generator.BlockPopulator; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.lang.reflect.Field; import java.nio.file.Path; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.OptionalLong; -import java.util.Random; -import java.util.concurrent.CompletableFuture; import java.util.function.BooleanSupplier; import java.util.function.Supplier; import static net.minecraft.core.registries.Registries.BIOME; -public class PaperweightRegen extends Regenerator { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); +public class PaperweightRegen extends Regenerator { private static final Field serverWorldsField; private static final Field paperConfigField; - private static final Field flatBedrockField; - private static final Field generatorSettingFlatField; private static final Field generatorSettingBaseSupplierField; - private static final Field delegateField; - private static final Field chunkSourceField; - private static final Field generatorStructureStateField; - private static final Field ringPositionsField; - private static final Field hasGeneratedPositionsField; - //list of chunk stati in correct order without FULL - private static final Map chunkStati = new LinkedHashMap<>(); static { - chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing - chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps - chunkStati.put( - ChunkStatus.STRUCTURE_REFERENCES, - Concurrency.NONE - ); // structure refs: radius 8, but only writes to current chunk - chunkStati.put(ChunkStatus.BIOMES, Concurrency.NONE); // biomes: radius 0 - chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8 - chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE - chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results - chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps - chunkStati.put( - ChunkStatus.INITIALIZE_LIGHT, - Concurrency.FULL - ); // initialize_light: radius 0 - chunkStati.put( - ChunkStatus.LIGHT, - Concurrency.FULL - ); // light: radius 1, but no writes to other chunks, only current chunk - chunkStati.put(ChunkStatus.SPAWN, Concurrency.NONE); // spawn: radius 0 - try { serverWorldsField = CraftServer.class.getDeclaredField("worlds"); serverWorldsField.setAccessible(true); Field tmpPaperConfigField; - Field tmpFlatBedrockField; try { //only present on paper tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); tmpPaperConfigField.setAccessible(true); - - tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock"); - tmpFlatBedrockField.setAccessible(true); } catch (Exception e) { tmpPaperConfigField = null; - tmpFlatBedrockField = null; } paperConfigField = tmpPaperConfigField; - flatBedrockField = tmpFlatBedrockField; generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( "settings", "e")); generatorSettingBaseSupplierField.setAccessible(true); - - generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "d")); - generatorSettingFlatField.setAccessible(true); - - delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); - delegateField.setAccessible(true); - - chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "I")); - chunkSourceField.setAccessible(true); - - generatorStructureStateField = ChunkMap.class.getDeclaredField(Refraction.pickName("chunkGeneratorState", "v")); - generatorStructureStateField.setAccessible(true); - - ringPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(Refraction.pickName("ringPositions", "g")); - ringPositionsField.setAccessible(true); - - hasGeneratedPositionsField = ChunkGeneratorStructureState.class.getDeclaredField( - Refraction.pickName("hasGeneratedPositions", "h") - ); - hasGeneratedPositionsField.setAccessible(true); } catch (Exception e) { throw new RuntimeException(e); } @@ -171,44 +78,37 @@ public class PaperweightRegen extends Regenerator super.chunkStatuses.put(new ChunkStatusWrap(s), c)); - return true; } @Override - @SuppressWarnings("unchecked") protected boolean initNewWorld() throws Exception { //world folder tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); @@ -254,8 +154,10 @@ public class PaperweightRegen extends Regenerator getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { if (options.hasBiomeType()) { return singleBiome; } - return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome( - biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler() - ); + return super.getUncachedNoiseBiome(biomeX, biomeY, biomeZ); } + @Override + public void save( + @org.jetbrains.annotations.Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled + ) { + // noop, spigot + } + + @Override + public void save( + @Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled, + final boolean close + ) { + // noop, paper + } }).get(); freshWorld.noSave = true; removeWorldFromWorldsMap(); @@ -293,93 +207,6 @@ public class PaperweightRegen extends Regenerator generatorSettingBaseSupplier = (Holder) - generatorSettingBaseSupplierField.get(noiseBasedChunkGenerator); - BiomeSource biomeSource; - if (options.hasBiomeType()) { - biomeSource = new FixedBiomeSource( - DedicatedServer.getServer().registryAccess() - .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) - ); - } else { - biomeSource = originalGenerator.getBiomeSource(); - } - chunkGenerator = new NoiseBasedChunkGenerator( - biomeSource, - generatorSettingBaseSupplier - ); - } else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) { - chunkGenerator = customChunkGenerator.getDelegate(); - } else { - LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName()); - return false; - } - if (generator != null) { - chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); - generateConcurrent = generator.isParallelCapable(); - } -// chunkGenerator.conf = freshWorld.spigotConfig; - Does not exist anymore, may need to be re-addressed - - freshChunkProvider = new ServerChunkCache( - freshWorld, - session, - server.getFixerUpper(), - server.getStructureManager(), - server.executor, - chunkGenerator, - freshWorld.spigotConfig.viewDistance, - freshWorld.spigotConfig.simulationDistance, - server.forceSynchronousWrites(), - new RegenNoOpWorldLoadListener(), - (chunkCoordIntPair, state) -> { - }, - () -> server.overworld().getDataStorage() - ) { - // redirect to LevelChunks created in #createChunks - @Override - public ChunkAccess getChunk(int x, int z, @NotNull ChunkStatus chunkstatus, boolean create) { - ChunkAccess chunkAccess = getChunkAt(x, z); - if (chunkAccess == null && create) { - chunkAccess = createChunk(getProtoChunkAt(x, z)); - } - return chunkAccess; - } - }; - - if (seed == originalOpts.seed() && !options.hasBiomeType()) { - // Optimisation for needless ring position calculation when the seed and biome is the same. - ChunkGeneratorStructureState state = (ChunkGeneratorStructureState) generatorStructureStateField.get( - originalChunkProvider.chunkMap); - boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(state); - if (hasGeneratedPositions) { - Map>> origPositions = - (Map>>) ringPositionsField.get(state); - Map>> copy = new Object2ObjectArrayMap<>( - origPositions); - ChunkGeneratorStructureState newState = (ChunkGeneratorStructureState) generatorStructureStateField.get( - freshChunkProvider.chunkMap); - ringPositionsField.set(newState, copy); - hasGeneratedPositionsField.setBoolean(newState, true); - } - } - - - chunkSourceField.set(freshWorld, freshChunkProvider); - //let's start then - structureTemplateManager = server.getStructureManager(); - threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider); - - this.worldGenContext = new WorldGenContext(freshWorld, chunkGenerator, structureTemplateManager, - threadedLevelLightEngine - ); return true; } @@ -394,7 +221,8 @@ public class PaperweightRegen extends Regenerator { try { - freshChunkProvider.close(false); + freshWorld.getChunkSource().getDataStorage().cache.clear(); + freshWorld.getChunkSource().close(false); } catch (Exception e) { throw new RuntimeException(e); } @@ -415,50 +243,9 @@ public class PaperweightRegen extends Regenerator getBlockPopulators() { - return originalServerWorld.getWorld().getPopulators(); - } - - @Override - protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { - // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> { - final CraftWorld world = freshWorld.getWorld(); - final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ); - blockPopulator.populate(world, random, chunk); - }); - } - @Override protected IChunkCache initSourceQueueCache() { - return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) { - @Override - public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) { - return getChunkAt(x, z); - } - }; + return new ChunkCache<>(BukkitAdapter.adapt(freshWorld.getWorld())); } //util @@ -512,83 +299,4 @@ public class PaperweightRegen extends Regenerator biomeRegistry, - @Nullable final BlendingData blendingData - ) { - super(pos, upgradeData, world, biomeRegistry, blendingData); - } - - // avoid warning on paper - - @SuppressWarnings("unused") // compatibility with spigot - public boolean generateFlatBedrock() { - return generateFlatBedrock; - } - - // no one will ever see the entities! - @Override - public @NotNull List getEntities() { - return Collections.emptyList(); - } - - } - - protected class ChunkStatusWrap extends ChunkStatusWrapper { - - private final ChunkStatus chunkStatus; - - public ChunkStatusWrap(ChunkStatus chunkStatus) { - this.chunkStatus = chunkStatus; - } - - @Override - public int requiredNeighborChunkRadius() { - return chunkStatus.getRange(); - } - - @Override - public String name() { - return chunkStatus.toString(); - } - - @Override - public CompletableFuture processChunk(List accessibleChunks) { - return chunkStatus.generate( - worldGenContext, - Runnable::run, - CompletableFuture::completedFuture, - accessibleChunks - ); - } - - } - - /** - * A light engine that does nothing. As light is calculated after pasting anyway, we can avoid - * work this way. - */ - static class NoOpLightEngine extends ThreadedLevelLightEngine { - - private static final ProcessorMailbox MAILBOX = ProcessorMailbox.create(task -> { - }, "fawe-no-op"); - private static final ProcessorHandle> HANDLE = ProcessorHandle.of("fawe-no-op", m -> { - }); - - public NoOpLightEngine(final ServerChunkCache chunkProvider) { - super(chunkProvider, chunkProvider.chunkMap, false, MAILBOX, HANDLE); - } - - @Override - public @NotNull CompletableFuture lightChunk(final @NotNull ChunkAccess chunk, final boolean excludeBlocks) { - return CompletableFuture.completedFuture(chunk); - } - - } - } diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweAdapter.java index 9452024c5..34fc70f8d 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightFaweAdapter.java @@ -19,6 +19,7 @@ import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.nbt.PaperweightLazyCompoundTag; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1.regen.PaperweightRegen; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; @@ -565,7 +566,7 @@ public final class PaperweightFaweAdapter extends FaweAdapter { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); +public class PaperweightRegen extends Regenerator { private static final Field serverWorldsField; private static final Field paperConfigField; - private static final Field flatBedrockField; - private static final Field generatorSettingFlatField; private static final Field generatorSettingBaseSupplierField; - private static final Field delegateField; - private static final Field chunkSourceField; - private static final Field generatorStructureStateField; - private static final Field ringPositionsField; - private static final Field hasGeneratedPositionsField; - //list of chunk stati in correct order without FULL - private static final Map chunkStati = new LinkedHashMap<>(); static { - chunkStati.put(ChunkStatus.EMPTY, Concurrency.FULL); // empty: radius -1, does nothing - chunkStati.put(ChunkStatus.STRUCTURE_STARTS, Concurrency.NONE); // structure starts: uses unsynchronized maps - chunkStati.put( - ChunkStatus.STRUCTURE_REFERENCES, - Concurrency.NONE - ); // structure refs: radius 8, but only writes to current chunk - chunkStati.put(ChunkStatus.BIOMES, Concurrency.NONE); // biomes: radius 0 - chunkStati.put(ChunkStatus.NOISE, Concurrency.RADIUS); // noise: radius 8 - chunkStati.put(ChunkStatus.SURFACE, Concurrency.NONE); // surface: radius 0, requires NONE - chunkStati.put(ChunkStatus.CARVERS, Concurrency.NONE); // carvers: radius 0, but RADIUS and FULL change results - chunkStati.put(ChunkStatus.FEATURES, Concurrency.NONE); // features: uses unsynchronized maps - chunkStati.put( - ChunkStatus.INITIALIZE_LIGHT, - Concurrency.FULL - ); // initialize_light: radius 0 - chunkStati.put( - ChunkStatus.LIGHT, - Concurrency.FULL - ); // light: radius 1, but no writes to other chunks, only current chunk - chunkStati.put(ChunkStatus.SPAWN, Concurrency.NONE); // spawn: radius 0 - try { serverWorldsField = CraftServer.class.getDeclaredField("worlds"); serverWorldsField.setAccessible(true); Field tmpPaperConfigField; - Field tmpFlatBedrockField; try { //only present on paper tmpPaperConfigField = Level.class.getDeclaredField("paperConfig"); tmpPaperConfigField.setAccessible(true); - - tmpFlatBedrockField = tmpPaperConfigField.getType().getDeclaredField("generateFlatBedrock"); - tmpFlatBedrockField.setAccessible(true); } catch (Exception e) { tmpPaperConfigField = null; - tmpFlatBedrockField = null; } paperConfigField = tmpPaperConfigField; - flatBedrockField = tmpFlatBedrockField; generatorSettingBaseSupplierField = NoiseBasedChunkGenerator.class.getDeclaredField(Refraction.pickName( "settings", "e")); generatorSettingBaseSupplierField.setAccessible(true); - - generatorSettingFlatField = FlatLevelSource.class.getDeclaredField(Refraction.pickName("settings", "d")); - generatorSettingFlatField.setAccessible(true); - - delegateField = CustomChunkGenerator.class.getDeclaredField("delegate"); - delegateField.setAccessible(true); - - chunkSourceField = ServerLevel.class.getDeclaredField(Refraction.pickName("chunkSource", "I")); - chunkSourceField.setAccessible(true); - - generatorStructureStateField = ChunkMap.class.getDeclaredField(Refraction.pickName("chunkGeneratorState", "w")); - generatorStructureStateField.setAccessible(true); - - ringPositionsField = ChunkGeneratorStructureState.class.getDeclaredField(Refraction.pickName("ringPositions", "g")); - ringPositionsField.setAccessible(true); - - hasGeneratedPositionsField = ChunkGeneratorStructureState.class.getDeclaredField( - Refraction.pickName("hasGeneratedPositions", "h") - ); - hasGeneratedPositionsField.setAccessible(true); } catch (Exception e) { throw new RuntimeException(e); } @@ -177,47 +78,37 @@ public class PaperweightRegen extends Regenerator super.chunkStatuses.put(new ChunkStatusWrap(s), c)); - return true; } @Override - @SuppressWarnings("unchecked") protected boolean initNewWorld() throws Exception { //world folder tempDir = java.nio.file.Files.createTempDirectory("FastAsyncWorldEditWorldGen"); @@ -263,8 +154,10 @@ public class PaperweightRegen extends Regenerator getUncachedNoiseBiome(int biomeX, int biomeY, int biomeZ) { if (options.hasBiomeType()) { return singleBiome; } - return PaperweightRegen.this.chunkGenerator.getBiomeSource().getNoiseBiome( - biomeX, biomeY, biomeZ, getChunkSource().randomState().sampler() - ); + return super.getUncachedNoiseBiome(biomeX, biomeY, biomeZ); } + @Override + public void save( + @Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled + ) { + // noop, spigot + } + + @Override + public void save( + @Nullable final ProgressListener progressListener, + final boolean flush, + final boolean savingDisabled, + final boolean close + ) { + // noop, paper + } }).get(); freshWorld.noSave = true; removeWorldFromWorldsMap(); @@ -302,97 +207,6 @@ public class PaperweightRegen extends Regenerator generatorSettingBaseSupplier = (Holder) - generatorSettingBaseSupplierField.get(noiseBasedChunkGenerator); - BiomeSource biomeSource; - if (options.hasBiomeType()) { - biomeSource = new FixedBiomeSource( - DedicatedServer.getServer().registryAccess() - .registryOrThrow(BIOME).asHolderIdMap().byIdOrThrow( - WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBiomeId(options.getBiomeType()) - ) - ); - } else { - biomeSource = originalGenerator.getBiomeSource(); - } - chunkGenerator = new NoiseBasedChunkGenerator( - biomeSource, - generatorSettingBaseSupplier - ); - } else if (originalGenerator instanceof CustomChunkGenerator customChunkGenerator) { - chunkGenerator = customChunkGenerator.getDelegate(); - } else { - LOGGER.error("Unsupported generator type {}", originalGenerator.getClass().getName()); - return false; - } - if (generator != null) { - chunkGenerator = new CustomChunkGenerator(freshWorld, chunkGenerator, generator); - generateConcurrent = generator.isParallelCapable(); - } -// chunkGenerator.conf = freshWorld.spigotConfig; - Does not exist anymore, may need to be re-addressed - - freshChunkProvider = new ServerChunkCache( - freshWorld, - session, - server.getFixerUpper(), - server.getStructureManager(), - server.executor, - chunkGenerator, - freshWorld.spigotConfig.viewDistance, - freshWorld.spigotConfig.simulationDistance, - server.forceSynchronousWrites(), - new RegenNoOpWorldLoadListener(), - (chunkCoordIntPair, state) -> { - }, - () -> server.overworld().getDataStorage() - ) { - // redirect to LevelChunks created in #createChunks - @Override - public ChunkAccess getChunk(int x, int z, @NotNull ChunkStatus chunkstatus, boolean create) { - ChunkAccess chunkAccess = getChunkAt(x, z); - if (chunkAccess == null && create) { - chunkAccess = createChunk(getProtoChunkAt(x, z)); - } - return chunkAccess; - } - }; - - if (seed == originalOpts.seed() && !options.hasBiomeType()) { - // Optimisation for needless ring position calculation when the seed and biome is the same. - ChunkGeneratorStructureState state = (ChunkGeneratorStructureState) generatorStructureStateField.get( - originalChunkProvider.chunkMap); - boolean hasGeneratedPositions = hasGeneratedPositionsField.getBoolean(state); - if (hasGeneratedPositions) { - Map>> origPositions = - (Map>>) ringPositionsField.get(state); - Map>> copy = new Object2ObjectArrayMap<>( - origPositions); - ChunkGeneratorStructureState newState = (ChunkGeneratorStructureState) generatorStructureStateField.get( - freshChunkProvider.chunkMap); - ringPositionsField.set(newState, copy); - hasGeneratedPositionsField.setBoolean(newState, true); - } - } - - - chunkSourceField.set(freshWorld, freshChunkProvider); - //let's start then - structureTemplateManager = server.getStructureManager(); - threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider); - - this.worldGenContext = new WorldGenContext( - freshWorld, - chunkGenerator, - structureTemplateManager, - threadedLevelLightEngine, - originalChunkProvider.chunkMap.worldGenContext.mainThreadMailBox() - ); return true; } @@ -407,7 +221,8 @@ public class PaperweightRegen extends Regenerator { try { - freshChunkProvider.close(false); + freshWorld.getChunkSource().getDataStorage().cache.clear(); + freshWorld.getChunkSource().close(false); } catch (Exception e) { throw new RuntimeException(e); } @@ -428,50 +243,9 @@ public class PaperweightRegen extends Regenerator getBlockPopulators() { - return originalServerWorld.getWorld().getPopulators(); - } - - @Override - protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { - // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> { - final CraftWorld world = freshWorld.getWorld(); - final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ); - blockPopulator.populate(world, random, chunk); - }); - } - @Override protected IChunkCache initSourceQueueCache() { - return (chunkX, chunkZ) -> new PaperweightGetBlocks(freshWorld, chunkX, chunkZ) { - @Override - public LevelChunk ensureLoaded(ServerLevel nmsWorld, int x, int z) { - return getChunkAt(x, z); - } - }; + return new ChunkCache<>(BukkitAdapter.adapt(freshWorld.getWorld())); } //util @@ -525,99 +299,4 @@ public class PaperweightRegen extends Regenerator biomeRegistry, - @Nullable final BlendingData blendingData - ) { - super(pos, upgradeData, world, biomeRegistry, blendingData); - } - - // avoid warning on paper - - @SuppressWarnings("unused") // compatibility with spigot - public boolean generateFlatBedrock() { - return generateFlatBedrock; - } - - // no one will ever see the entities! - @Override - public @NotNull List getEntities() { - return Collections.emptyList(); - } - - } - - protected class ChunkStatusWrap extends ChunkStatusWrapper { - - private final ChunkStatus chunkStatus; - - public ChunkStatusWrap(ChunkStatus chunkStatus) { - this.chunkStatus = chunkStatus; - } - - @Override - public int requiredNeighborChunkRadius() { - return ChunkPyramid.GENERATION_PYRAMID.getStepTo(ChunkStatus.FULL).getAccumulatedRadiusOf(chunkStatus); - } - - @Override - public String name() { - return chunkStatus.toString(); - } - - @Override - public CompletableFuture processChunk(List accessibleChunks) { - ChunkAccess chunkAccess = accessibleChunks.get(accessibleChunks.size() / 2); - int chunkX = chunkAccess.getPos().x; - int chunkZ = chunkAccess.getPos().z; - getProtoChunkAt(chunkX, chunkZ); - StaticCache2D neighbours = StaticCache2D - .create( - chunkX, - chunkZ, - requiredNeighborChunkRadius(), - (final int nx, final int nz) -> new ChunkHolder(new ChunkPos(nx, nz), - ChunkHolderManager.MAX_TICKET_LEVEL, - freshWorld, - threadedLevelLightEngine, - null, - freshChunkProvider.chunkMap - ) - ); - return ChunkPyramid.GENERATION_PYRAMID.getStepTo(chunkStatus).apply( - worldGenContext, - neighbours, - chunkAccess - ); - } - - } - - /** - * A light engine that does nothing. As light is calculated after pasting anyway, we can avoid - * work this way. - */ - static class NoOpLightEngine extends ThreadedLevelLightEngine { - - private static final ProcessorMailbox MAILBOX = ProcessorMailbox.create(task -> { - }, "fawe-no-op"); - private static final ProcessorHandle> HANDLE = ProcessorHandle.of("fawe-no-op", m -> { - }); - - public NoOpLightEngine(final ServerChunkCache chunkProvider) { - super(chunkProvider, chunkProvider.chunkMap, false, MAILBOX, HANDLE); - } - - @Override - public @NotNull CompletableFuture lightChunk(final @NotNull ChunkAccess chunk, final boolean excludeBlocks) { - return CompletableFuture.completedFuture(chunk); - } - - } - } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java index 4afbe03a2..ac75a29f6 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java @@ -1,67 +1,32 @@ package com.fastasyncworldedit.bukkit.adapter; -import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.queue.IChunkCache; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent; -import com.fastasyncworldedit.core.util.MathMan; -import com.google.common.collect.Lists; -import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.fastasyncworldedit.core.util.TaskManager; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.RegenOptions; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongArrayList; -import it.unimi.dsi.fastutil.longs.LongList; -import jdk.jfr.Category; -import jdk.jfr.Event; -import jdk.jfr.Label; -import jdk.jfr.Name; -import org.apache.logging.log4j.Logger; import org.bukkit.generator.BiomeProvider; -import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.WorldInfo; -import java.util.AbstractList; -import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Random; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; import java.util.function.Function; /** * Represents an abstract regeneration handler. - * - * @param the type of the {@code IChunkAccess} of the current Minecraft implementation - * @param the type of the {@code ProtoChunk} of the current Minecraft implementation - * @param the type of the {@code Chunk} of the current Minecraft implementation - * @param the type of the {@code ChunkStatusWrapper} wrapping the {@code ChunkStatus} enum */ -public abstract class Regenerator> { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); +public abstract class Regenerator { protected final org.bukkit.World originalBukkitWorld; protected final Region region; @@ -69,13 +34,8 @@ public abstract class Regenerator chunkStatuses = new LinkedHashMap<>(); // TODO (j21): use SequencedMap - private final Long2ObjectLinkedOpenHashMap protoChunks = new Long2ObjectLinkedOpenHashMap<>(); - private final Long2ObjectOpenHashMap chunks = new Long2ObjectOpenHashMap<>(); - protected boolean generateConcurrent = true; protected long seed; - private ExecutorService executor; - private SingleThreadQueueExtent source; + protected SingleThreadQueueExtent source; /** * Initializes an abstract regeneration handler. @@ -92,15 +52,6 @@ public abstract class Regenerator chunkCoordsForChunkStatus = new LinkedHashMap<>(); - int borderSum = 1; - // TODO (j21): use SequencedMap#sequencedKeySet().reversed() - final List reversedKeys = Lists.reverse(new ArrayList<>(chunkStatuses.keySet())); - for (final ChunkStatus status : reversedKeys) { - chunkCoordsForChunkStatus.put(status, getChunkCoordsRegen(region, borderSum)); - borderSum += status.requiredNeighborChunkRadius(); - } - - //create chunks - // TODO (j21): use SequencedMap#firstEntry().getKey() - for (long xz : chunkCoordsForChunkStatus.get(chunkStatuses.keySet().iterator().next())) { - ProtoChunk chunk = createProtoChunk(MathMan.unpairIntX(xz), MathMan.unpairIntY(xz)); - protoChunks.put(xz, chunk); - } - - // a memory-efficient, lightweight "list" that calculates index -> ChunkAccess - // as needed when accessed - class LazyChunkList extends AbstractList { - private final int size; - private final int minX; - private final int minZ; - private final int sizeSqrt; - - LazyChunkList(int radius, int centerX, int centerZ) { - this.sizeSqrt = radius + 1 + radius; // length of one side - this.size = this.sizeSqrt * this.sizeSqrt; - this.minX = centerX - radius; - this.minZ = centerZ - radius; - } - @Override - public IChunkAccess get(final int index) { - Objects.checkIndex(index, size); - int absX = (index % sizeSqrt) + minX; - int absZ = (index / sizeSqrt) + minZ; - return protoChunks.get(MathMan.pairInt(absX, absZ)); - } - - @Override - public int size() { - return size; - } - - } - @Label("Regeneration") - @Category("FAWE") - @Name("fawe.regen") - class RegenerationEvent extends Event { - private String chunkStatus; - private int chunksToProcess; - } - - //run generation tasks excluding FULL chunk status - for (Map.Entry entry : chunkStatuses.entrySet()) { - ChunkStatus chunkStatus = entry.getKey(); - final RegenerationEvent event = new RegenerationEvent(); - event.begin(); - event.chunkStatus = chunkStatus.name(); - int radius = Math.max(1, chunkStatus.requiredNeighborChunkRadius0()); - - long[] coords = chunkCoordsForChunkStatus.get(chunkStatus); - event.chunksToProcess = coords.length; - if (this.generateConcurrent && entry.getValue() == Concurrency.RADIUS) { - SequentialTasks> tasks = getChunkStatusTaskRows(coords, radius); - for (ConcurrentTasks para : tasks) { - List scheduled = new ArrayList<>(tasks.size()); - for (LongList row : para) { - scheduled.add(() -> { - for (long xz : row) { - chunkStatus.processChunkSave(xz, new LazyChunkList(radius, MathMan.unpairIntX(xz), - MathMan.unpairIntY(xz))); - } - }); - } - runAndWait(scheduled); - } - } else if (this.generateConcurrent && entry.getValue() == Concurrency.FULL) { - // every chunk can be processed individually - List scheduled = new ArrayList<>(coords.length); - for (long xz : coords) { - scheduled.add(() -> chunkStatus.processChunkSave(xz, new LazyChunkList(radius, MathMan.unpairIntX(xz), - MathMan.unpairIntY(xz)))); - } - runAndWait(scheduled); - } else { // Concurrency.NONE or generateConcurrent == false - // run sequential but submit to different thread - // running regen on the main thread otherwise triggers async-only events on the main thread - executor.submit(() -> { - for (long xz : coords) { - chunkStatus.processChunkSave(xz, new LazyChunkList(radius, MathMan.unpairIntX(xz), - MathMan.unpairIntY(xz))); - } - }).get(); // wait until finished this step - } - event.commit(); - } - - //convert to proper chunks - // TODO (j21): use SequencedMap#firstEntry().getValue() - for (long xz : chunkCoordsForChunkStatus.values().iterator().next()) { - ProtoChunk proto = protoChunks.get(xz); - chunks.put(xz, createChunk(proto)); - } - - //final chunkstatus - ChunkStatus FULL = getFullChunkStatus(); - // TODO (j21): use SequencedMap#firstEntry().getValue() - for (long xz : chunkCoordsForChunkStatus.values().iterator().next()) { //FULL.requiredNeighbourChunkRadius() == 0! - Chunk chunk = chunks.get(xz); - FULL.processChunkSave(xz, List.of(chunk)); - } - - //populate - List populators = getBlockPopulators(); - // TODO (j21): use SequencedMap#firstEntry().getValue() - for (long xz : chunkCoordsForChunkStatus.values().iterator().next()) { - int x = MathMan.unpairIntX(xz); - int z = MathMan.unpairIntY(xz); - - //prepare chunk seed - Random random = getChunkRandom(seed, x, z); - - //actually populate - Chunk c = chunks.get(xz); - populators.forEach(pop -> { - populate(c, random, pop); - }); - } + private void createSource() { source = new SingleThreadQueueExtent( BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMinHeight() : 0, BukkitWorld.HAS_MIN_Y ? originalBukkitWorld.getMaxHeight() : 256 ); source.init(target, initSourceQueueCache(), null); - return true; - } - - private void runAndWait(final List tasks) { - try { - List> futures = new ArrayList<>(); - tasks.forEach(task -> futures.add(executor.submit(task))); - for (Future future : futures) { - future.get(); - } - } catch (Exception e) { - LOGGER.catching(e); - } } private void copyToWorld() { + createSource(); + final long timeoutPerTick = TimeUnit.MILLISECONDS.toNanos(10); + int taskId = TaskManager.taskManager().repeat(() -> { + final long startTime = System.nanoTime(); + runTasks(() -> System.nanoTime() - startTime < timeoutPerTick); + }, 1); //Setting Blocks boolean genbiomes = options.shouldRegenBiomes(); boolean hasBiome = options.hasBiomeType(); @@ -343,6 +117,7 @@ public abstract class Regenerator source.getBiome(vec))); } + TaskManager.taskManager().cancel(taskId); } private class PlacementPattern implements Pattern { @@ -382,9 +157,6 @@ public abstract class Regenerator getBlockPopulators(); - - /** - * Implement the population of the {@code Chunk} with the given chunk random and {@code BlockPopulator} here. - * - * @param chunk the {@code Chunk} to populate - * @param random the chunk random to use for population - * @param pop the {@code BlockPopulator} to use - */ - protected abstract void populate(Chunk chunk, Random random, BlockPopulator pop); - /** * Implement the initialization an {@code IChunkCache} here. Use will need the {@code getChunkAt} function * @@ -464,106 +195,6 @@ public abstract class Regenerator initSourceQueueCache(); - //algorithms - private long[] getChunkCoordsRegen(Region region, int border) { //needs to be square num of chunks - BlockVector3 oldMin = region.getMinimumPoint(); - BlockVector3 newMin = BlockVector3.at( - (oldMin.x() >> 4 << 4) - border * 16, - oldMin.y(), - (oldMin.z() >> 4 << 4) - border * 16 - ); - BlockVector3 oldMax = region.getMaximumPoint(); - BlockVector3 newMax = BlockVector3.at( - (oldMax.x() >> 4 << 4) + (border + 1) * 16 - 1, - oldMax.y(), - (oldMax.z() >> 4 << 4) + (border + 1) * 16 - 1 - ); - Region adjustedRegion = new CuboidRegion(newMin, newMax); - return adjustedRegion.getChunks().stream() - .sorted(Comparator - .comparingInt(BlockVector2::z) - .thenComparingInt(BlockVector2::x)) //needed for RegionLimitedWorldAccess - .mapToLong(c -> MathMan.pairInt(c.x(), c.z())) - .toArray(); - } - - /** - * Creates a list of chunkcoord rows that may be executed concurrently - * - * @param allCoords the coords that should be sorted into rows, must be sorted by z and x - * @param requiredNeighborChunkRadius the radius of neighbor chunks that may not be written to concurrently (ChunkStatus - * .requiredNeighborRadius) - * @return a list of chunkcoords rows that may be executed concurrently - */ - private SequentialTasks> getChunkStatusTaskRows( - long[] allCoords, - int requiredNeighborChunkRadius - ) { - int requiredNeighbors = Math.max(0, requiredNeighborChunkRadius); - - final int coordsCount = allCoords.length; - long first = coordsCount == 0 ? 0 : allCoords[0]; - long last = coordsCount == 0 ? 0 : allCoords[coordsCount - 1]; - int minX = MathMan.unpairIntX(first); - int maxX = MathMan.unpairIntX(last); - int minZ = MathMan.unpairIntY(first); - int maxZ = MathMan.unpairIntY(last); - SequentialTasks> tasks; - if (maxZ - minZ > maxX - minX) { - int numlists = Math.min(requiredNeighbors * 2 + 1, maxX - minX + 1); - - Int2ObjectOpenHashMap byX = new Int2ObjectOpenHashMap<>(); - int expectedListLength = (coordsCount + 1) / (maxX - minX); - - //init lists - for (int i = minX; i <= maxX; i++) { - byX.put(i, new LongArrayList(expectedListLength)); - } - - //sort into lists by x coord - for (long allCoord : allCoords) { - byX.get(MathMan.unpairIntX(allCoord)).add(allCoord); - } - - //create parallel tasks - tasks = new SequentialTasks<>(numlists); - for (int offset = 0; offset < numlists; offset++) { - ConcurrentTasks para = new ConcurrentTasks<>((maxZ - minZ + 1) / numlists + 1); - for (int i = 0; minX + i * numlists + offset <= maxX; i++) { - para.add(byX.get(minX + i * numlists + offset)); - } - tasks.add(para); - } - } else { - int numlists = Math.min(requiredNeighbors * 2 + 1, maxZ - minZ + 1); - - Int2ObjectOpenHashMap byZ = new Int2ObjectOpenHashMap<>(); - int expectedListLength = (coordsCount + 1) / (maxZ - minZ + 2); - - //init lists - for (int i = minZ; i <= maxZ; i++) { - byZ.put(i, new LongArrayList(expectedListLength)); - } - - //sort into lists by x coord - for (long allCoord : allCoords) { - byZ.get(MathMan.unpairIntY(allCoord)).add(allCoord); - } - - //create parallel tasks - tasks = new SequentialTasks<>(numlists); - for (int offset = 0; offset < numlists; offset++) { - ConcurrentTasks para = new ConcurrentTasks<>((maxX - minX + 1) / numlists + 1); - for (int i = 0; minZ + i * numlists + offset <= maxZ; i++) { - para.add(byZ.get(minZ + i * numlists + offset)); - } - tasks.add(para); - } - } - - return tasks; - } - protected BiomeProvider getBiomeProvider() { if (options.hasBiomeType()) { return new SingleBiomeProvider(); @@ -579,103 +210,6 @@ public abstract class Regenerator the IChunkAccess class of the current Minecraft implementation - */ - public static abstract class ChunkStatusWrapper { - - /** - * Return the required neighbor chunk radius the wrapped {@code ChunkStatus} requires. - * - * @return the radius of required neighbor chunks - */ - public abstract int requiredNeighborChunkRadius(); - - int requiredNeighborChunkRadius0() { - return Math.max(0, requiredNeighborChunkRadius()); - } - - /** - * Return the name of the wrapped {@code ChunkStatus}. - * - * @return the radius of required neighbor chunks - */ - public abstract String name(); - - /** - * Return the name of the wrapped {@code ChunkStatus}. - * - * @param accessibleChunks a list of chunks that will be used during the execution of the wrapped {@code ChunkStatus}. - * This list is order in the correct order required by the {@code ChunkStatus}, unless Mojang suddenly decides to do things differently. - */ - public abstract CompletableFuture processChunk(List accessibleChunks); - - void processChunkSave(long xz, List accessibleChunks) { - try { - processChunk(accessibleChunks).get(); - } catch (Exception e) { - LOGGER.error("Error while running {} on chunk {}/{}", - name(), MathMan.unpairIntX(xz), MathMan.unpairIntY(xz), e); - } - } - - @Override - public String toString() { - return name(); - } - - } - - public static class SequentialTasks extends Tasks { - - public SequentialTasks(int expectedSize) { - super(expectedSize); - } - - } - - public static class ConcurrentTasks extends Tasks { - - public ConcurrentTasks(int expectedSize) { - super(expectedSize); - } - - } - - public static class Tasks implements Iterable { - - private final List tasks; - - public Tasks(int expectedSize) { - tasks = new ArrayList<>(expectedSize); - } - - public void add(T task) { - tasks.add(task); - } - - public List list() { - return tasks; - } - - public int size() { - return tasks.size(); - } - - @Override - public Iterator iterator() { - return tasks.iterator(); - } - - @Override - public String toString() { - return tasks.toString(); - } - - } - public class SingleBiomeProvider extends BiomeProvider { private final org.bukkit.block.Biome biome = BukkitAdapter.adapt(options.getBiomeType()); From f820cb2fb4cf982c27a919d7b173668857964a9e Mon Sep 17 00:00:00 2001 From: Alexander Brandes Date: Sun, 15 Sep 2024 14:34:04 +0200 Subject: [PATCH 25/59] Update javadoc url of paper 1.21.1 Signed-off-by: Alexander Brandes --- buildSrc/src/main/kotlin/CommonJavaConfig.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/CommonJavaConfig.kt b/buildSrc/src/main/kotlin/CommonJavaConfig.kt index d221a98d2..155321fbc 100644 --- a/buildSrc/src/main/kotlin/CommonJavaConfig.kt +++ b/buildSrc/src/main/kotlin/CommonJavaConfig.kt @@ -61,7 +61,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean "https://jd.advntr.dev/api/latest/", "https://logging.apache.org/log4j/2.x/javadoc/log4j-api/", "https://www.antlr.org/api/Java/", - "https://jd.papermc.io/paper/1.21/", + "https://jd.papermc.io/paper/1.21.1/", "https://intellectualsites.github.io/fastasyncworldedit-javadocs/worldedit-core/" ) docTitle = "${rootProject.name}-${project.description}" + " " + "${rootProject.version}" From 49b063a1879e749035dacf801f19de15dcd118dc Mon Sep 17 00:00:00 2001 From: Jordan Date: Sun, 15 Sep 2024 16:00:17 +0100 Subject: [PATCH 26/59] fix: compound tags can be nullable when converting state to baseblock (#2914) --- .../core/extent/filter/block/CharFilterBlock.java | 3 +-- .../com/fastasyncworldedit/core/world/block/CompoundInput.java | 3 +-- .../com/sk89q/worldedit/extent/AbstractDelegateExtent.java | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java index b1862987f..74571af05 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java @@ -263,8 +263,7 @@ public class CharFilterBlock extends ChunkFilterBlock { final BlockMaterial material = state.getMaterial(); if (material.hasContainer()) { final FaweCompoundTag tag = get.tile(x, y + yy, z); - assert tag != null : "has container but is null"; - return state.toBaseBlock(tag.linTag()); + return state.toBaseBlock(tag == null ? null : tag.linTag()); } return state.toBaseBlock(); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java index 481f8d54f..eff3c3de6 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java @@ -17,8 +17,7 @@ public enum CompoundInput { @Override public BaseBlock get(final BlockState state, final IBlocks blocks, final int x, final int y, final int z) { final FaweCompoundTag tile = blocks.tile(x, y, z); - assert tile != null : "container without tile entity"; - return state.toBaseBlock(tile.linTag()); + return state.toBaseBlock(tile == null ? null : tile.linTag()); } }; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java index 267734247..89c450a10 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java @@ -427,7 +427,7 @@ public class AbstractDelegateExtent implements Extent { @Override public boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException { - return setBlock(x, y, z, getBlock(x, y, z).toBaseBlock(tile.linTag())); + return setBlock(x, y, z, getBlock(x, y, z).toBaseBlock(tile == null ? null : tile.linTag())); } //FAWE end From ea5589b1f031f2135a1c4d22018c347560edaddb Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sun, 15 Sep 2024 17:00:56 +0200 Subject: [PATCH 27/59] Introduce basic support for Vector API (#2890) * Introduce basic support for Vector API * add modules to javadoc too * add assumption comments --- build.gradle.kts | 2 +- buildSrc/src/main/kotlin/CommonJavaConfig.kt | 3 + .../core/configuration/Settings.java | 5 + .../core/extent/filter/CountFilter.java | 10 +- .../core/extent/filter/LinkedFilter.java | 36 ++++++- .../core/extent/filter/MaskFilter.java | 52 +++++++++- .../extent/filter/block/CharFilterBlock.java | 15 +-- .../core/internal/simd/SimdSupport.java | 99 +++++++++++++++++++ .../simd/VectorizedCharFilterBlock.java | 33 +++++++ .../core/internal/simd/VectorizedFilter.java | 8 ++ .../core/internal/simd/VectorizedMask.java | 40 ++++++++ .../core/queue/IQueueExtent.java | 9 +- .../implementation/ParallelQueueExtent.java | 6 +- .../sk89q/worldedit/extent/MaskingExtent.java | 22 ++++- .../sk89q/worldedit/function/mask/Mask.java | 18 ++++ 15 files changed, 341 insertions(+), 17 deletions(-) create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/SimdSupport.java create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedCharFilterBlock.java create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedFilter.java create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedMask.java diff --git a/build.gradle.kts b/build.gradle.kts index 5c8ce8016..afe45594c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -91,7 +91,7 @@ tasks { minecraftVersion(it) pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } .toTypedArray()) - jvmArgs("-DPaper.IgnoreJavaVersion=true", "-Dcom.mojang.eula.agree=true") + jvmArgs("-DPaper.IgnoreJavaVersion=true", "-Dcom.mojang.eula.agree=true", "--add-modules=jdk.incubator.vector") group = "run paper" runDirectory.set(file("run-$it")) } diff --git a/buildSrc/src/main/kotlin/CommonJavaConfig.kt b/buildSrc/src/main/kotlin/CommonJavaConfig.kt index 155321fbc..ea921709c 100644 --- a/buildSrc/src/main/kotlin/CommonJavaConfig.kt +++ b/buildSrc/src/main/kotlin/CommonJavaConfig.kt @@ -28,6 +28,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean options.isDeprecation = true options.encoding = "UTF-8" options.compilerArgs.add("-parameters") + options.compilerArgs.add("--add-modules=jdk.incubator.vector") } configurations.all { @@ -51,12 +52,14 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean tasks.withType().configureEach { (options as StandardJavadocDocletOptions).apply { addStringOption("Xdoclint:none", "-quiet") + addStringOption("-add-modules", "jdk.incubator.vector") tags( "apiNote:a:API Note:", "implSpec:a:Implementation Requirements:", "implNote:a:Implementation Note:" ) options.encoding = "UTF-8" + links( "https://jd.advntr.dev/api/latest/", "https://logging.apache.org/log4j/2.x/javadoc/log4j-api/", diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java index 4db469187..d35219bec 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java @@ -675,6 +675,11 @@ public class Settings extends Config { }) public boolean ALLOW_TICK_FLUIDS = false; + @Comment({ + "Whether FAWE should use the incubator Vector API to accelerate some operations" + }) + public boolean USE_VECTOR_API = false; + } @Comment({"Web/HTTP connection related settings"}) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/CountFilter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/CountFilter.java index 72ee73013..f6844e684 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/CountFilter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/CountFilter.java @@ -1,8 +1,10 @@ package com.fastasyncworldedit.core.extent.filter; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; +import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; +import jdk.incubator.vector.ShortVector; -public class CountFilter extends ForkedFilter { +public class CountFilter extends ForkedFilter implements VectorizedFilter { private int total; @@ -33,4 +35,10 @@ public class CountFilter extends ForkedFilter { return total; } + @Override + public ShortVector applyVector(final ShortVector get, final ShortVector set) { + total += set.length(); + return set; + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/LinkedFilter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/LinkedFilter.java index 25627c451..a600fc180 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/LinkedFilter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/LinkedFilter.java @@ -2,7 +2,9 @@ package com.fastasyncworldedit.core.extent.filter; import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; +import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; import com.fastasyncworldedit.core.queue.Filter; +import jdk.incubator.vector.ShortVector; /** * Filter which links two Filters together for single-filter-input operations. @@ -10,10 +12,18 @@ import com.fastasyncworldedit.core.queue.Filter; * @param Parent which extends Filter * @param Child which extends Filter */ -public final class LinkedFilter extends DelegateFilter { +public sealed class LinkedFilter extends DelegateFilter { private final S child; + @SuppressWarnings({"unchecked", "rawtypes"}) // we defeated the type system + public static LinkedFilter of(T parent, S child) { + if (parent instanceof VectorizedFilter p && child instanceof VectorizedFilter c) { + return new VectorizedLinkedFilter(p, c); + } + return new LinkedFilter<>(parent, child); + } + public LinkedFilter(T parent, S child) { super(parent); this.child = child; @@ -30,8 +40,30 @@ public final class LinkedFilter extends Dele } @Override - public LinkedFilter, Filter> newInstance(Filter other) { + public LinkedFilter, ? extends Filter> newInstance(Filter other) { return new LinkedFilter<>(this, other); } + private final static class VectorizedLinkedFilter + extends LinkedFilter implements VectorizedFilter { + + public VectorizedLinkedFilter(final T parent, final S child) { + super(parent, child); + } + + @Override + public ShortVector applyVector(final ShortVector get, final ShortVector set) { + ShortVector res = getParent().applyVector(get, set); + return getChild().applyVector(get, res); + } + + @Override + public LinkedFilter, Filter> newInstance(Filter other) { + if (other instanceof VectorizedFilter o) { + return new VectorizedLinkedFilter(this, o); + } + return new LinkedFilter<>(this, other); + } + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/MaskFilter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/MaskFilter.java index 9284f8378..ac31938e2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/MaskFilter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/MaskFilter.java @@ -2,10 +2,17 @@ package com.fastasyncworldedit.core.extent.filter; import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; +import com.fastasyncworldedit.core.internal.simd.SimdSupport; +import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; +import com.fastasyncworldedit.core.internal.simd.VectorizedMask; import com.fastasyncworldedit.core.queue.Filter; import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.Mask; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorOperators; +import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; /** @@ -15,8 +22,8 @@ import java.util.concurrent.atomic.AtomicInteger; */ public class MaskFilter extends DelegateFilter { - private final Mask mask; - private final AtomicInteger changes; + final Mask mask; + final AtomicInteger changes; public MaskFilter(T other, Mask root) { this(other, root, new AtomicInteger()); @@ -60,4 +67,45 @@ public class MaskFilter extends DelegateFilter { return new MaskFilter<>(getParent().fork(), mask.copy(), changes); } + public static class VectorizedMaskFilter extends MaskFilter implements VectorizedFilter { + + private final VectorizedMask vectorizedMask; + + public VectorizedMaskFilter(final T other, final Mask root) { + super(other, root); + this.vectorizedMask = Objects.requireNonNull(SimdSupport.vectorizedTargetMask(root), "invalid vectorizable mask"); + } + + public VectorizedMaskFilter(final T other, final Mask root, AtomicInteger changes) { + super(other, root, changes); + this.vectorizedMask = Objects.requireNonNull(SimdSupport.vectorizedTargetMask(root), "invalid vectorizable mask"); + } + + @Override + public ShortVector applyVector(final ShortVector get, final ShortVector set) { + final T parent = getParent(); + VectorMask masked = vectorizedMask.compareVector(set, get); + ShortVector res = parent.applyVector(get, set); + res = set.blend(res, masked); + VectorMask changed = res.compare(VectorOperators.NE, set); + changes.getAndAdd(changed.trueCount()); + return res; + } + + @Override + public MaskFilter newInstance(final Filter other) { + if (other instanceof VectorizedFilter o) { + return new VectorizedMaskFilter<>(o, mask); + } + return super.newInstance(other); + } + + @SuppressWarnings("unchecked") + @Override + public Filter fork() { + return new VectorizedMaskFilter<>((T) getParent().fork(), mask.copy(), changes); + } + + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java index 74571af05..cafd4513a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java @@ -23,12 +23,14 @@ import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.registry.BlockMaterial; import org.enginehub.linbus.tree.LinCompoundTag; +import org.jetbrains.annotations.ApiStatus; import javax.annotation.Nonnull; import javax.annotation.Nullable; import static com.sk89q.worldedit.world.block.BlockTypesCache.states; +@ApiStatus.NonExtendable public class CharFilterBlock extends ChunkFilterBlock { private static final SetDelegate FULL = (block, value) -> block.setArr[block.index] = value; @@ -38,10 +40,10 @@ public class CharFilterBlock extends ChunkFilterBlock { private int minLayer; private CharGetBlocks get; private IChunkSet set; - private char[] getArr; + protected char[] getArr; @Nullable - private char[] setArr; - private SetDelegate delegate; + protected char[] setArr; + protected SetDelegate delegate; // local private int layer; private int index; @@ -172,7 +174,7 @@ public class CharFilterBlock extends ChunkFilterBlock { } @Override - public synchronized final void filter(Filter filter) { + public synchronized void filter(Filter filter) { for (y = 0, index = 0; y < 16; y++) { for (z = 0; z < 16; z++) { for (x = 0; x < 16; x++, index++) { @@ -395,7 +397,7 @@ public class CharFilterBlock extends ChunkFilterBlock { } //Set delegate - private SetDelegate initSet() { + protected final SetDelegate initSet() { setArr = set.load(layer); return delegate = FULL; } @@ -427,7 +429,8 @@ public class CharFilterBlock extends ChunkFilterBlock { return getExtent().setBiome(x, y, z, biome); } - private interface SetDelegate { + @ApiStatus.Internal + protected interface SetDelegate { void set(@Nonnull CharFilterBlock block, char value); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/SimdSupport.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/SimdSupport.java new file mode 100644 index 000000000..23d135fa6 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/SimdSupport.java @@ -0,0 +1,99 @@ +package com.fastasyncworldedit.core.internal.simd; + +import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter; +import com.fastasyncworldedit.core.function.mask.SingleBlockStateMask; +import com.fastasyncworldedit.core.queue.Filter; +import com.sk89q.worldedit.function.mask.InverseSingleBlockStateMask; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.util.LogManagerCompat; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.VectorOperators; + +import javax.annotation.Nullable; + +public class SimdSupport { + + private static final boolean VECTOR_API_PRESENT; + + static { + boolean vectorApiPresent = false; + try { + Class.forName("jdk.incubator.vector.Vector"); + vectorApiPresent = true; + } catch (ClassNotFoundException ignored) { + } + VECTOR_API_PRESENT = vectorApiPresent; + if (!VECTOR_API_PRESENT && Settings.settings().EXPERIMENTAL.USE_VECTOR_API) { + LogManagerCompat.getLogger() + .warn("FAWE use-vector-api is enabled but --add-modules=jdk.incubator.vector is not set."); + } + } + + public static boolean useVectorApi() { + return VECTOR_API_PRESENT && Settings.settings().EXPERIMENTAL.USE_VECTOR_API; + } + + public static @Nullable VectorizedMask vectorizedTargetMask(Mask mask) { + if (!useVectorApi()) { + return null; + } + return switch (mask) { + case SingleBlockStateMask single -> vectorizedTargetMask(single.getBlockState().getOrdinalChar()); + case InverseSingleBlockStateMask inverse -> vectorizedTargetMaskInverse(inverse.getBlockState().getOrdinalChar()); + default -> null; + }; + } + + private static VectorizedMask vectorizedTargetMask(char ordinal) { + return (set, get) -> get.compare(VectorOperators.EQ, (short) ordinal); + } + + private static VectorizedMask vectorizedTargetMaskInverse(char ordinal) { + return (set, get) -> get.compare(VectorOperators.NE, (short) ordinal); + } + + public static @Nullable VectorizedFilter vectorizedPattern(Pattern pattern) { + if (!useVectorApi()) { + return null; + } + return switch (pattern) { + case BaseBlock block -> { + if (block.getNbtReference() == null) { + yield new VectorizedPattern<>(block, block.getOrdinalChar()); + } + yield null; + } + case BlockStateHolder blockStateHolder -> new VectorizedPattern<>( + blockStateHolder, + blockStateHolder.getOrdinalChar() + ); + default -> null; + }; + } + + private static final class VectorizedPattern extends DelegateFilter implements VectorizedFilter { + + private final char ordinal; + + public VectorizedPattern(final T parent, char ordinal) { + super(parent); + this.ordinal = ordinal; + } + + @Override + public ShortVector applyVector(final ShortVector get, final ShortVector set) { + return ShortVector.broadcast(ShortVector.SPECIES_PREFERRED, ordinal); + } + + @Override + public Filter newInstance(final Filter other) { + return new VectorizedPattern<>(other, ordinal); + } + + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedCharFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedCharFilterBlock.java new file mode 100644 index 000000000..5c15da22a --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedCharFilterBlock.java @@ -0,0 +1,33 @@ +package com.fastasyncworldedit.core.internal.simd; + +import com.fastasyncworldedit.core.extent.filter.block.CharFilterBlock; +import com.fastasyncworldedit.core.queue.Filter; +import com.sk89q.worldedit.extent.Extent; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.VectorSpecies; + +public class VectorizedCharFilterBlock extends CharFilterBlock { + + public VectorizedCharFilterBlock(final Extent extent) { + super(extent); + } + + @Override + public synchronized void filter(final Filter filter) { + if (!(filter instanceof VectorizedFilter vecFilter)) { + throw new IllegalStateException("Unexpected VectorizedCharFilterBlock " + filter); + } + final VectorSpecies species = ShortVector.SPECIES_PREFERRED; + initSet(); // set array is null before + char[] setArr = this.setArr; + assert setArr != null; + char[] getArr = this.getArr; + // assume setArr.length == getArr.length == 4096 + for (int i = 0; i < 4096; i += species.length()) { + ShortVector set = ShortVector.fromCharArray(species, setArr, i); + ShortVector get = ShortVector.fromCharArray(species, getArr, i); + ShortVector res = vecFilter.applyVector(get, set); + res.intoCharArray(setArr, i); + } + } +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedFilter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedFilter.java new file mode 100644 index 000000000..7357bbd59 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedFilter.java @@ -0,0 +1,8 @@ +package com.fastasyncworldedit.core.internal.simd; + +import com.fastasyncworldedit.core.queue.Filter; +import jdk.incubator.vector.ShortVector; + +public interface VectorizedFilter extends Filter { + ShortVector applyVector(ShortVector get, ShortVector set); +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedMask.java new file mode 100644 index 000000000..0f453f32b --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/VectorizedMask.java @@ -0,0 +1,40 @@ +package com.fastasyncworldedit.core.internal.simd; + +import com.fastasyncworldedit.core.queue.IChunk; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.IChunkSet; +import jdk.incubator.vector.ShortVector; +import jdk.incubator.vector.VectorMask; +import jdk.incubator.vector.VectorSpecies; + +public interface VectorizedMask { + + default void processChunks(IChunk chunk, IChunkGet get, IChunkSet set) { + for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) { + final char[] sectionSet = set.loadIfPresent(layer); + if (sectionSet == null) { + continue; + } + final char[] sectionGet = get.load(layer); + processSection(layer, sectionSet, sectionGet); + } + } + + default void processSection(int layer, char[] set, char[] get) { + final VectorSpecies species = ShortVector.SPECIES_PREFERRED; + // assume that set.length % species.elementSize() == 0 + for (int i = 0; i < set.length; i += species.length()) { + ShortVector vectorSet = ShortVector.fromCharArray(species, set, i); + ShortVector vectorGet = ShortVector.fromCharArray(species, get, i); + vectorSet = processVector(vectorSet, vectorGet); + vectorSet.intoCharArray(set, i); + } + } + + default ShortVector processVector(ShortVector set, ShortVector get) { + return set.blend(0, compareVector(set, get).not()); + } + + VectorMask compareVector(ShortVector set, ShortVector get); + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java index 3f104b35d..ee3740411 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java @@ -2,6 +2,9 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.processor.IBatchProcessorHolder; +import com.fastasyncworldedit.core.internal.simd.SimdSupport; +import com.fastasyncworldedit.core.internal.simd.VectorizedCharFilterBlock; +import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.math.BlockVector2; @@ -146,7 +149,11 @@ public interface IQueueExtent extends Flushable, Trimable, ICh if (newChunk != null) { chunk = newChunk; if (block == null) { - block = this.createFilterBlock(); + if (SimdSupport.useVectorApi() && filter instanceof VectorizedFilter) { + block = new VectorizedCharFilterBlock(this); + } else { + block = this.createFilterBlock(); + } } block.initChunk(chunkX, chunkZ); chunk.filterBlocks(filter, block, region, full); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java index 1b56afdbc..f197524f3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java @@ -14,6 +14,8 @@ import com.fastasyncworldedit.core.extent.processor.BatchProcessorHolder; import com.fastasyncworldedit.core.extent.processor.MultiBatchProcessor; import com.fastasyncworldedit.core.function.mask.BlockMaskBuilder; import com.fastasyncworldedit.core.internal.exception.FaweException; +import com.fastasyncworldedit.core.internal.simd.SimdSupport; +import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; @@ -223,7 +225,9 @@ public class ParallelQueueExtent extends PassthroughExtent { @Override public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { - return this.changes = apply(region, new LinkedFilter<>(pattern, new CountFilter()), true).getChild().getTotal(); + VectorizedFilter vectorizedPattern = SimdSupport.vectorizedPattern(pattern); + var filter = LinkedFilter.of(vectorizedPattern == null ? pattern : vectorizedPattern, new CountFilter()); + return this.changes = apply(region, filter, true).getChild().getTotal(); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java index 0abc80153..77f9aa1c7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java @@ -24,6 +24,8 @@ import com.fastasyncworldedit.core.extent.filter.block.CharFilterBlock; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; +import com.fastasyncworldedit.core.internal.simd.SimdSupport; +import com.fastasyncworldedit.core.internal.simd.VectorizedMask; import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunk; @@ -35,6 +37,7 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockStateHolder; +import javax.annotation.Nullable; import java.util.function.LongFunction; import static com.google.common.base.Preconditions.checkNotNull; @@ -47,6 +50,7 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce //FAWE start private final LongFunction getOrCreateFilterBlock; private Mask mask; + private @Nullable VectorizedMask vectorizedMask; //FAWE end /** @@ -59,16 +63,23 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce super(extent); checkNotNull(mask); this.mask = mask; + this.vectorizedMask = SimdSupport.vectorizedTargetMask(mask); //FAWE start this.getOrCreateFilterBlock = FaweCache.INSTANCE.createMainThreadSafeCache(() -> new CharFilterBlock(getExtent())); //FAWE end } //FAWE start - private MaskingExtent(Extent extent, Mask mask, LongFunction getOrCreateFilterBlock) { + private MaskingExtent( + Extent extent, + Mask mask, + LongFunction getOrCreateFilterBlock, + @Nullable VectorizedMask vectorizedMask + ) { super(extent); checkNotNull(mask); this.mask = mask; + this.vectorizedMask = vectorizedMask; this.getOrCreateFilterBlock = getOrCreateFilterBlock; } //FAWE end @@ -90,6 +101,7 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce public void setMask(Mask mask) { checkNotNull(mask); this.mask = mask; + this.vectorizedMask = SimdSupport.vectorizedTargetMask(mask); } //FAWE start @@ -105,6 +117,10 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce @Override public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { + if (this.vectorizedMask != null) { + this.vectorizedMask.processChunks(chunk, get, set); + return set; + } final ChunkFilterBlock filter = getOrCreateFilterBlock.apply(Thread.currentThread().getId()); filter.initChunk(chunk.getX(), chunk.getZ()); return filter.filter(chunk, get, set, this); @@ -122,12 +138,12 @@ public class MaskingExtent extends AbstractDelegateExtent implements IBatchProce if (child == getExtent()) { return this; } - return new MaskingExtent(child, this.mask.copy(), this.getOrCreateFilterBlock); + return new MaskingExtent(child, this.mask.copy(), this.getOrCreateFilterBlock, this.vectorizedMask); } @Override public Filter fork() { - return new MaskingExtent(getExtent(), this.mask.copy(), this.getOrCreateFilterBlock); + return new MaskingExtent(getExtent(), this.mask.copy(), this.getOrCreateFilterBlock, this.vectorizedMask); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java index 94141278d..85e85a8c2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java @@ -22,7 +22,11 @@ package com.sk89q.worldedit.function.mask; import com.fastasyncworldedit.core.extent.filter.MaskFilter; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; import com.fastasyncworldedit.core.function.mask.InverseMask; +import com.fastasyncworldedit.core.internal.simd.SimdSupport; +import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; +import com.fastasyncworldedit.core.internal.simd.VectorizedMask; import com.fastasyncworldedit.core.queue.Filter; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import javax.annotation.Nullable; @@ -64,7 +68,21 @@ public interface Mask { return null; } + @SuppressWarnings({"unchecked", "rawtypes"}) default MaskFilter toFilter(T filter) { + final VectorizedMask mask = SimdSupport.vectorizedTargetMask(this); + if (mask != null) { + VectorizedFilter vectorizedFilter = null; + if (filter instanceof VectorizedFilter vf) { + vectorizedFilter = vf; + } else if (filter instanceof Pattern p) { + vectorizedFilter = SimdSupport.vectorizedPattern(p); + } + if (vectorizedFilter != null) { + // also pass original? + return new MaskFilter.VectorizedMaskFilter(vectorizedFilter, this); + } + } return new MaskFilter<>(filter, this); } From 5ef7461b503665df310a6d04a9fd8fee4c2e0d15 Mon Sep 17 00:00:00 2001 From: Alexander Brandes Date: Sun, 15 Sep 2024 17:20:01 +0200 Subject: [PATCH 28/59] Release 2.11.2 Signed-off-by: Alexander Brandes --- .../core/history/change/ChangePopulator.java | 2 +- .../history/changeset/AbstractChangeSet.java | 18 +++++++++--------- .../changeset/ChangeExchangeCoordinator.java | 2 +- .../core/nbt/FaweCompoundTag.java | 2 +- .../fastasyncworldedit/core/queue/IBlocks.java | 6 +++--- .../core/queue/IChunkGet.java | 4 ++-- .../core/queue/IChunkSet.java | 4 ++-- .../core/queue/ITileInput.java | 2 +- .../fastasyncworldedit/core/util/MainUtil.java | 4 ++-- .../fastasyncworldedit/core/util/NbtUtils.java | 10 +++++----- .../core/world/block/CompoundInput.java | 2 +- .../src/main/java/com/sk89q/jnbt/NBTUtils.java | 2 +- .../sk89q/worldedit/extent/OutputExtent.java | 4 ++-- .../extent/clipboard/BlockArrayClipboard.java | 2 +- .../com/sk89q/worldedit/math/BlockVector3.java | 2 +- .../world/registry/BlockMaterial.java | 2 +- 16 files changed, 34 insertions(+), 34 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/ChangePopulator.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/ChangePopulator.java index 6831a443c..84424d948 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/ChangePopulator.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/ChangePopulator.java @@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** - * @since TODO + * @since 2.11.2 */ @ApiStatus.Internal public interface ChangePopulator { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java index 3e60cb4eb..33931aac6 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java @@ -242,7 +242,7 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { return ProcessorScope.READING_SET_BLOCKS; } - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") public void addTileCreate(CompoundTag tag) { addTileCreate(adapt(tag)); } @@ -256,11 +256,11 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { * Creates a tile/block entity create change to this change set. * * @param tag the tile/block entity to add. - * @since TODO + * @since 2.11.2 */ public abstract void addTileCreate(FaweCompoundTag tag); - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") public void addTileRemove(CompoundTag tag) { addTileRemove(adapt(tag)); } @@ -269,11 +269,11 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { * Creates a tile/block entity remove change to this change set. * * @param tag the tile/block entity to remove. - * @since TODO + * @since 2.11.2 */ public abstract void addTileRemove(FaweCompoundTag tag); - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") public void addEntityRemove(CompoundTag tag) { addEntityRemove(adapt(tag)); } @@ -282,11 +282,11 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { * Creates an entity remove change to this change set. * * @param tag the entity to remove. - * @since TODO + * @since 2.11.2 */ public abstract void addEntityRemove(FaweCompoundTag tag); - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") public void addEntityCreate(CompoundTag tag) { addEntityCreate(adapt(tag)); } @@ -295,7 +295,7 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { * Creates an entity create change to this change set. * * @param tag the entity to add. - * @since TODO + * @since 2.11.2 */ public abstract void addEntityCreate(FaweCompoundTag tag); @@ -307,7 +307,7 @@ public abstract class AbstractChangeSet implements ChangeSet, IBatchProcessor { /** * {@return a coordinator to exchange sets of changes between a producer and a consumer} - * @since TODO + * @since 2.11.2 */ @ApiStatus.Internal public abstract ChangeExchangeCoordinator getCoordinatedChanges(BlockBag blockBag, int mode, boolean dir); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java index 56d47500f..2f3398a60 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java @@ -7,7 +7,7 @@ import java.util.concurrent.Exchanger; import java.util.function.BiConsumer; /** - * @since TODO + * @since 2.11.2 */ @ApiStatus.Internal public class ChangeExchangeCoordinator implements AutoCloseable { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/FaweCompoundTag.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/FaweCompoundTag.java index a244f7964..52e38908d 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/FaweCompoundTag.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/nbt/FaweCompoundTag.java @@ -7,7 +7,7 @@ import org.enginehub.linbus.tree.LinCompoundTag; /** * A wrapper around compound tags, potentially lazily transformed. - * @since TODO + * @since 2.11.2 */ public sealed interface FaweCompoundTag permits EagerFaweCompoundTag, LazyFaweCompoundTag { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java index b14b7b39d..bda12dbe3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java @@ -59,14 +59,14 @@ public interface IBlocks extends Trimable { BlockState getBlock(int x, int y, int z); - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") default Map getTiles() { return AdaptedMap.immutable(tiles(), pos -> pos, IBlocks::toCompoundTag); } Map tiles(); - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") default CompoundTag getTile(int x, int y, int z) { final FaweCompoundTag tile = tile(x, y, z); if (tile == null) { @@ -83,7 +83,7 @@ public interface IBlocks extends Trimable { @Nullable FaweCompoundTag tile(int x, int y, int z); - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") default Set getEntities() { return entities().stream() .map(IBlocks::toCompoundTag) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java index 1ead25284..b72690029 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java @@ -47,7 +47,7 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent, ITileInput { > T call(IChunkSet set, Runnable finalize); - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") default CompoundTag getEntity(UUID uuid) { final FaweCompoundTag entity = entity(uuid); if (entity == null) { @@ -63,7 +63,7 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent, ITileInput { @Nullable FaweCompoundTag entity(UUID uuid); @Override - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") default CompoundTag getTile(int x, int y, int z) { return IBlocks.super.getTile(x, y, z); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java index 13400f769..fc1482d6e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java @@ -38,7 +38,7 @@ public interface IChunkSet extends IBlocks, OutputExtent { boolean isEmpty(); @Override - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") default boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { return tile(x, y, z, FaweCompoundTag.of(tile.toLinTag())); } @@ -60,7 +60,7 @@ public interface IChunkSet extends IBlocks, OutputExtent { void setFullBright(int layer); - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") default void setEntity(CompoundTag tag) { entity(FaweCompoundTag.of(tag::toLinTag)); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/ITileInput.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/ITileInput.java index eb0503858..4a88118ef 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/ITileInput.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/ITileInput.java @@ -2,7 +2,7 @@ package com.fastasyncworldedit.core.queue; import com.sk89q.jnbt.CompoundTag; -@Deprecated(forRemoval = true, since = "TODO") +@Deprecated(forRemoval = true, since = "2.11.2") public interface ITileInput { CompoundTag getTile(int x, int y, int z); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java index 115397788..04da475e2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/MainUtil.java @@ -428,7 +428,7 @@ public class MainUtil { * @deprecated use {@link NbtUtils#withPosition} instead */ @Nonnull - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") public static CompoundTag setPosition(@Nonnull CompoundTag tag, int x, int y, int z) { Map> value = new HashMap<>(tag.getValue()); value.put("x", new IntTag(x)); @@ -446,7 +446,7 @@ public class MainUtil { * @deprecated use {@link NbtUtils#withEntityInfo(LinCompoundTag, Entity)} instead */ @Nonnull - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") public static CompoundTag setEntityInfo(@Nonnull CompoundTag tag, @Nonnull Entity entity) { Map> map = new HashMap<>(tag.getValue()); map.put("Id", new StringTag(entity.getState().getType().id())); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java index 07a752131..ac606ab24 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java @@ -96,7 +96,7 @@ public final class NbtUtils { * * @param compoundTag the compound tag to extract uuid information from * @return the extracted UUID - * @since TODO + * @since 2.11.2 */ public static UUID uuid(FaweCompoundTag compoundTag) { final LinCompoundTag linTag = compoundTag.linTag(); @@ -139,7 +139,7 @@ public final class NbtUtils { * @param y New Y coordinate * @param z New Z coordinate * @return New tag - * @since TODO + * @since 2.11.2 */ public static @Nonnull LinCompoundTag withPosition(@Nonnull LinCompoundTag tag, int x, int y, int z) { return tag.toBuilder() @@ -157,7 +157,7 @@ public final class NbtUtils { * @param y New Y coordinate * @param z New Z coordinate * @return New tag - * @since TODO + * @since 2.11.2 */ public static @Nonnull FaweCompoundTag withPosition(@Nonnull FaweCompoundTag tag, int x, int y, int z) { return FaweCompoundTag.of(withPosition(tag.linTag(), x, y, z)); @@ -168,7 +168,7 @@ public final class NbtUtils { * * @param tag the tag to copy * @param entity the entity to use the Id and the Pos from - * @since TODO + * @since 2.11.2 */ public static @Nonnull LinCompoundTag withEntityInfo(@Nonnull LinCompoundTag tag, @Nonnull Entity entity) { final LinCompoundTag.Builder builder = tag.toBuilder() @@ -191,7 +191,7 @@ public final class NbtUtils { * * @param map the map to insert to * @param uuid the uuid to insert - * @since TODO + * @since 2.11.2 */ public static void addUUIDToMap(Map> map, UUID uuid) { int[] uuidArray = new int[4]; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java index eff3c3de6..37c63a042 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/world/block/CompoundInput.java @@ -21,7 +21,7 @@ public enum CompoundInput { } }; - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") public BaseBlock get(BlockState state, ITileInput input, int x, int y, int z) { return state.toBaseBlock(); } diff --git a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java index 11143a6c7..9b28a6d30 100644 --- a/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java +++ b/worldedit-core/src/main/java/com/sk89q/jnbt/NBTUtils.java @@ -174,7 +174,7 @@ public final class NBTUtils { * @since 2.4.0 * @deprecated use {@link com.fastasyncworldedit.core.util.NbtUtils#addUUIDToMap(Map, UUID)} instead */ - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") public static void addUUIDToMap(Map> map, UUID uuid) { int[] uuidArray = new int[4]; uuidArray[0] = (int) (uuid.getMostSignificantBits() >> 32); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java index 1e988b51f..b38e2dc2d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/OutputExtent.java @@ -72,7 +72,7 @@ public interface OutputExtent { /** * @deprecated use {@link #tile(int, int, int, FaweCompoundTag)} instead */ - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") default boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { return tile(x, y, z, FaweCompoundTag.of(tile.toLinTag())); } @@ -84,7 +84,7 @@ public interface OutputExtent { * @param z the z position * @param tile the tile/block entity to set * @return {@code true} if the tile/block entity was placed - * @since TODO + * @since 2.11.2 */ boolean tile(int x, int y, int z, FaweCompoundTag tile) throws WorldEditException; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java index e67c28abf..9ff666f79 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/BlockArrayClipboard.java @@ -209,7 +209,7 @@ public class BlockArrayClipboard implements Clipboard { } - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") public boolean setTile(BlockVector3 position, CompoundTag tag) { return tile(position.x(), position.y(), position.z(), FaweCompoundTag.of(tag.toLinTag())); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java index d8dc989da..017ec7ca0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/BlockVector3.java @@ -852,7 +852,7 @@ public abstract class BlockVector3 { return orDefault.getBiome(this); } - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.11.2") public CompoundTag getNbtData(Extent orDefault) { return orDefault.getFullBlock(x(), y(), z()).getNbtData(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java index d37929a37..243acb171 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/registry/BlockMaterial.java @@ -196,7 +196,7 @@ public interface BlockMaterial { /** * {@return the default tile associated with this material, if any} - * @since TODO + * @since 2.11.2 */ @Nullable FaweCompoundTag defaultTile(); From 526f1f7b7632b149ae1daba5c1b4aa61bb03f856 Mon Sep 17 00:00:00 2001 From: Alexander Brandes Date: Sun, 15 Sep 2024 17:23:15 +0200 Subject: [PATCH 29/59] Back to snapshot for development Signed-off-by: Alexander Brandes --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index afe45594c..dddd41149 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -52,7 +52,7 @@ ext { } } -version = String.format("%s-%s", rootVersion, buildNumber) +version = String.format("%s", rootVersion) if (!project.hasProperty("gitCommitHash")) { apply(plugin = "org.ajoberstar.grgit") From c2496543bd2e121fd4d253abd15122e026baf6f7 Mon Sep 17 00:00:00 2001 From: Alexander Brandes Date: Sun, 15 Sep 2024 17:32:58 +0200 Subject: [PATCH 30/59] Update runServer task for 1.21.1 Signed-off-by: Alexander Brandes --- build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index dddd41149..adab2bddb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,7 +34,7 @@ logger.lifecycle(""" ******************************************* """) -var rootVersion by extra("2.11.2") +var rootVersion by extra("2.11.3") var snapshot by extra("SNAPSHOT") var revision: String by extra("") var buildNumber by extra("") @@ -52,7 +52,7 @@ ext { } } -version = String.format("%s", rootVersion) +version = String.format("%s-%s", rootVersion, buildNumber) if (!project.hasProperty("gitCommitHash")) { apply(plugin = "org.ajoberstar.grgit") @@ -97,7 +97,7 @@ tasks { } } runServer { - minecraftVersion("1.20.4") + minecraftVersion("1.21.1") pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } .toTypedArray()) From b5be1477a50da3e25ef21eeab5fa62206392f85b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 00:46:47 +0000 Subject: [PATCH 31/59] Update dependency com.gradleup.shadow:shadow-gradle-plugin to v8.3.1 (#2915) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 7b227e2d8..b4d03430f 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -23,7 +23,7 @@ val properties = Properties().also { props -> dependencies { implementation(gradleApi()) implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2") - implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.0") + implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.1") implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.2") constraints { val asmVersion = "[9.7,)" From 7010c8181ffaa7b446e92ac6f01183f0df1027c6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 00:47:02 +0000 Subject: [PATCH 32/59] Update dependency com.palmergames.bukkit.towny:towny to v0.100.4.1 (#2916) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 004644b3f..3927910c9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ mapmanager = "1.8.0-SNAPSHOT" griefprevention = "17.0.0" griefdefender = "2.1.0-SNAPSHOT" residence = "4.5._13.1" -towny = "0.100.3.13" +towny = "0.100.4.1" plotsquared = "7.3.10" # Third party From 789907e56b8911fb259e3afed4e68cd591a66ca0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 04:04:37 +0000 Subject: [PATCH 33/59] Update dependency gradle to v8.10.1 (#2918) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9355b4155..0aaefbcaf 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 71b99f9b05805832ef90bf70ac2d5bf5d30ca97c Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Mon, 16 Sep 2024 20:41:58 +0200 Subject: [PATCH 34/59] Revert history writing using LinBinaryIO (#2919) --- .../changeset/FaweStreamChangeSet.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java index 613b8def8..e50030d21 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java @@ -22,12 +22,9 @@ import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockTypes; -import org.enginehub.linbus.stream.LinBinaryIO; -import org.enginehub.linbus.tree.LinRootEntry; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.DataOutput; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; @@ -405,8 +402,8 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { public void addTileCreate(final FaweCompoundTag tag) { blockSize++; try { - DataOutput nbtos = getTileCreateOS(); - LinBinaryIO.write(nbtos, new LinRootEntry("tile-create", tag.linTag())); + NBTOutputStream nbtos = getTileCreateOS(); + nbtos.writeTag(new CompoundTag(tag.linTag())); } catch (IOException e) { e.printStackTrace(); } @@ -416,8 +413,8 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { public void addTileRemove(final FaweCompoundTag tag) { blockSize++; try { - DataOutput nbtos = getTileRemoveOS(); - LinBinaryIO.write(nbtos, new LinRootEntry("tile-remove", tag.linTag())); + NBTOutputStream nbtos = getTileRemoveOS(); + nbtos.writeTag(new CompoundTag(tag.linTag())); } catch (IOException e) { e.printStackTrace(); } @@ -427,8 +424,8 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { public void addEntityRemove(final FaweCompoundTag tag) { blockSize++; try { - DataOutput nbtos = getEntityRemoveOS(); - LinBinaryIO.write(nbtos, new LinRootEntry("entity-remove", tag.linTag())); + NBTOutputStream nbtos = getEntityRemoveOS(); + nbtos.writeTag(new CompoundTag(tag.linTag())); } catch (IOException e) { e.printStackTrace(); } @@ -438,8 +435,8 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet { public void addEntityCreate(final FaweCompoundTag tag) { blockSize++; try { - DataOutput nbtos = getEntityCreateOS(); - LinBinaryIO.write(nbtos, new LinRootEntry("entity-create", tag.linTag())); + NBTOutputStream nbtos = getEntityCreateOS(); + nbtos.writeTag(new CompoundTag(tag.linTag())); } catch (IOException e) { e.printStackTrace(); } From d9d5b7b4884860857b141deb5a42b29f5e502b1c Mon Sep 17 00:00:00 2001 From: Jordan Date: Tue, 17 Sep 2024 16:52:46 +0100 Subject: [PATCH 35/59] feat: improve fawe limits (#2773) (#2858) * feat: improve fawe limits (#2773) - add FaweLimit implementations for increasing concurrency levels - allow FaweLimit to perform processing (and forcefully disable as required) to capture [tile] entities - Use `BlockVector3#set(Extent orDefault)` where appropriate to reduce block checks - fixes #2679 - fixes #1874 (cherry picked from commit 6052fc3128410ec5dc9c2703b497082b8647d22c) * fix: actually apply a filter if applied from a full region chunk section - cannot remember why I made this change in the first place in #2773 but this fixes edits having "empty middles" - doesn't seem to have broken anything in testing * Reduce limit to always atomic --- .../fastasyncworldedit/core/FaweCache.java | 11 +- .../core/configuration/Settings.java | 40 ++-- .../platform/binding/EditSessionHolder.java | 7 + .../platform/binding/ProvideBindings.java | 34 ++- .../core/extent/LimitExtent.java | 196 +++++++++--------- .../extent/filter/block/CharFilterBlock.java | 1 - .../core/function/mask/ABlockMask.java | 2 +- .../core/function/mask/DataMask.java | 4 +- .../core/function/mask/IdMask.java | 4 +- .../function/mask/SingleBlockStateMask.java | 2 +- .../core/function/mask/SplatterBrushMask.java | 2 +- .../core/limit/FaweLimit.java | 134 ++++++++---- .../core/queue/IBatchProcessor.java | 2 +- .../java/com/sk89q/worldedit/EditSession.java | 19 +- .../sk89q/worldedit/EditSessionBuilder.java | 6 +- .../com/sk89q/worldedit/LocalSession.java | 2 +- .../worldedit/command/BiomeCommands.java | 2 + .../worldedit/command/BrushCommands.java | 10 +- .../worldedit/command/ClipboardCommands.java | 11 +- .../worldedit/command/GenerationCommands.java | 19 +- .../worldedit/command/HistoryCommands.java | 3 + .../worldedit/command/RegionCommands.java | 20 +- .../command/SnapshotUtilCommands.java | 2 + .../worldedit/command/UtilityCommands.java | 62 ++---- .../command/tool/BlockDataCyler.java | 2 +- .../worldedit/command/tool/BlockReplacer.java | 2 +- .../worldedit/command/tool/SinglePickaxe.java | 2 +- .../worldedit/command/tool/StackTool.java | 2 +- .../worldedit/command/tool/TreePlanter.java | 2 +- .../worldedit/command/tool/brush/Brush.java | 11 + .../util/annotation/ConfirmHandler.java | 2 +- .../util/annotation/PreloadHandler.java | 2 +- .../SynchronousSettingExpected.java | 22 ++ .../command/util/annotation/package-info.java | 1 + .../platform/PlatformCommandManager.java | 23 +- .../worldedit/function/mask/BiomeMask.java | 2 +- .../function/mask/BlockCategoryMask.java | 2 +- .../worldedit/function/mask/BlockMask.java | 2 +- .../function/mask/BlockStateMask.java | 2 +- .../function/mask/BlockTypeMask.java | 2 +- .../function/mask/ExistingBlockMask.java | 2 +- .../mask/InverseSingleBlockStateMask.java | 2 +- .../src/main/resources/lang/strings.json | 2 + 43 files changed, 400 insertions(+), 282 deletions(-) create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/EditSessionHolder.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/SynchronousSettingExpected.java diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java index 526570296..3ed494298 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java @@ -192,17 +192,22 @@ public enum FaweCache implements Trimable { Type.OUTSIDE_REGION ); public static final FaweException MAX_CHECKS = new FaweException( - Caption.of("fawe.cancel.reason.max" + ".checks"), + Caption.of("fawe.cancel.reason.max.checks"), + Type.MAX_CHECKS, + true + ); + public static final FaweException MAX_FAILS = new FaweException( + Caption.of("fawe.cancel.reason.max.fails"), Type.MAX_CHECKS, true ); public static final FaweException MAX_CHANGES = new FaweException( - Caption.of("fawe.cancel.reason.max" + ".changes"), + Caption.of("fawe.cancel.reason.max.changes"), Type.MAX_CHANGES, false ); public static final FaweException LOW_MEMORY = new FaweException( - Caption.of("fawe.cancel.reason.low" + ".memory"), + Caption.of("fawe.cancel.reason.low.memory"), Type.LOW_MEMORY, false ); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java index d35219bec..60ec9311a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java @@ -123,29 +123,31 @@ public class Settings extends Config { limit.MAX_ACTIONS, newLimit.MAX_ACTIONS != -1 ? newLimit.MAX_ACTIONS : Integer.MAX_VALUE ); - limit.MAX_CHANGES = Math.max( - limit.MAX_CHANGES, + limit.MAX_CHANGES.set(Math.max( + limit.MAX_CHANGES.get(), newLimit.MAX_CHANGES != -1 ? newLimit.MAX_CHANGES : Long.MAX_VALUE - ); - limit.MAX_BLOCKSTATES = Math.max( - limit.MAX_BLOCKSTATES, + )); + limit.MAX_BLOCKSTATES.set(Math.max( + limit.MAX_BLOCKSTATES.get(), newLimit.MAX_BLOCKSTATES != -1 ? newLimit.MAX_BLOCKSTATES : Integer.MAX_VALUE - ); - limit.MAX_CHECKS = Math.max( - limit.MAX_CHECKS, + )); + limit.MAX_CHECKS.set(Math.max( + limit.MAX_CHECKS.get(), newLimit.MAX_CHECKS != -1 ? newLimit.MAX_CHECKS : Long.MAX_VALUE - ); - limit.MAX_ENTITIES = Math.max( - limit.MAX_ENTITIES, + )); + limit.MAX_ENTITIES.set(Math.max( + limit.MAX_ENTITIES.get(), newLimit.MAX_ENTITIES != -1 ? newLimit.MAX_ENTITIES : Integer.MAX_VALUE - ); - limit.MAX_FAILS = Math.max(limit.MAX_FAILS, newLimit.MAX_FAILS != -1 ? newLimit.MAX_FAILS : Integer.MAX_VALUE); - limit.MAX_ITERATIONS = Math.max( - limit.MAX_ITERATIONS, newLimit.MAX_ITERATIONS != -1 ? newLimit.MAX_ITERATIONS : Integer.MAX_VALUE); - limit.MAX_RADIUS = Math.max( - limit.MAX_RADIUS, - newLimit.MAX_RADIUS != -1 ? newLimit.MAX_RADIUS : Integer.MAX_VALUE - ); + )); + limit.MAX_FAILS.set(Math.max( + limit.MAX_FAILS.get(), + newLimit.MAX_FAILS != -1 ? newLimit.MAX_FAILS : Integer.MAX_VALUE + )); + limit.MAX_ITERATIONS.set(Math.max( + limit.MAX_ITERATIONS.get(), + newLimit.MAX_ITERATIONS != -1 ? newLimit.MAX_ITERATIONS : Integer.MAX_VALUE + )); + limit.MAX_RADIUS = Math.max(limit.MAX_RADIUS, newLimit.MAX_RADIUS != -1 ? newLimit.MAX_RADIUS : Integer.MAX_VALUE); limit.MAX_SUPER_PICKAXE_SIZE = Math.max( limit.MAX_SUPER_PICKAXE_SIZE, newLimit.MAX_SUPER_PICKAXE_SIZE != -1 ? newLimit.MAX_SUPER_PICKAXE_SIZE : Integer.MAX_VALUE diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/EditSessionHolder.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/EditSessionHolder.java new file mode 100644 index 000000000..1fd588ec4 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/EditSessionHolder.java @@ -0,0 +1,7 @@ +package com.fastasyncworldedit.core.extension.platform.binding; + +import com.sk89q.worldedit.EditSession; + +public record EditSessionHolder(EditSession session) { + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/ProvideBindings.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/ProvideBindings.java index bc1e2bfbf..9ac01d9c3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/ProvideBindings.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/platform/binding/ProvideBindings.java @@ -3,7 +3,11 @@ package com.fastasyncworldedit.core.extension.platform.binding; import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.database.DBHandler; import com.fastasyncworldedit.core.database.RollbackDatabase; +import com.fastasyncworldedit.core.extent.LimitExtent; +import com.fastasyncworldedit.core.extent.processor.ExtentBatchProcessorHolder; +import com.fastasyncworldedit.core.internal.exception.FaweException; import com.fastasyncworldedit.core.regions.FaweMaskManager; +import com.fastasyncworldedit.core.util.ExtentTraverser; import com.fastasyncworldedit.core.util.TextureUtil; import com.fastasyncworldedit.core.util.image.ImageUtil; import com.sk89q.worldedit.EditSession; @@ -11,6 +15,7 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.util.annotation.AllowedRegion; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.platform.Actor; @@ -25,6 +30,7 @@ import org.enginehub.piston.inject.Key; import org.enginehub.piston.util.ValueProvider; import java.awt.image.BufferedImage; +import java.lang.reflect.Method; import java.net.URI; import java.util.Optional; @@ -52,11 +58,33 @@ public class ProvideBindings extends Bindings { @Binding public EditSession editSession(LocalSession localSession, Actor actor, InjectedValueAccess context) { + Method commandMethod = + context.injectedValue(Key.of(InjectedValueStore.class)).get().injectedValue(Key.of(Method.class)).get(); + Arguments arguments = context.injectedValue(Key.of(Arguments.class)).orElse(null); String command = arguments == null ? null : arguments.get(); - EditSession editSession = localSession.createEditSession(actor, command); - editSession.enableStandardMode(); - Request.request().setEditSession(editSession); + boolean synchronousSetting = commandMethod.getAnnotation(SynchronousSettingExpected.class) != null; + EditSessionHolder holder = context.injectedValue(Key.of(EditSessionHolder.class)).orElse(null); + EditSession editSession = holder != null ? holder.session() : null; + if (editSession == null) { + editSession = localSession.createEditSession(actor, command); + editSession.enableStandardMode(); + } else { + LimitExtent limitExtent = new ExtentTraverser<>(editSession).findAndGet(LimitExtent.class); + if (limitExtent != null) { + limitExtent.setProcessing(!synchronousSetting); + if (!synchronousSetting) { + ExtentBatchProcessorHolder processorHolder = new ExtentTraverser<>(editSession).findAndGet( + ExtentBatchProcessorHolder.class); + if (processorHolder != null) { + processorHolder.addProcessor(limitExtent); + } else { + throw new FaweException(Caption.of("fawe.error.no-process-non-synchronous-edit")); + } + } + } + Request.request().setEditSession(editSession); + } return editSession; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java index d02ff9320..d43078354 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java @@ -1,11 +1,15 @@ package com.fastasyncworldedit.core.extent; import com.fastasyncworldedit.core.extent.filter.block.ExtentFilterBlock; -import com.fastasyncworldedit.core.function.generator.GenBase; -import com.fastasyncworldedit.core.function.generator.Resource; +import com.fastasyncworldedit.core.extent.processor.ProcessorScope; import com.fastasyncworldedit.core.internal.exception.FaweException; import com.fastasyncworldedit.core.limit.FaweLimit; import com.fastasyncworldedit.core.queue.Filter; +import com.fastasyncworldedit.core.queue.IBatchProcessor; +import com.fastasyncworldedit.core.queue.IChunk; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.util.ExtentTraverser; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; @@ -17,7 +21,6 @@ import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.formatting.text.Component; @@ -37,18 +40,22 @@ import java.util.Set; import java.util.UUID; import java.util.function.Consumer; -public class LimitExtent extends AbstractDelegateExtent { +public class LimitExtent extends AbstractDelegateExtent implements IBatchProcessor { private final FaweLimit limit; private final boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length]; private final Consumer onErrorMessage; + private final int chunk_size; + private boolean processing; /** * Create a new instance. * * @param extent the extent * @param limit the limit + * @deprecated Use {@link LimitExtent#LimitExtent(Extent, FaweLimit, Consumer, boolean)} */ + @Deprecated(forRemoval = true, since = "TODO") public LimitExtent(Extent extent, FaweLimit limit) { this(extent, limit, c -> { }); @@ -60,11 +67,33 @@ public class LimitExtent extends AbstractDelegateExtent { * @param extent the extent * @param limit the limit * @param onErrorMessage consumer to handle a component generated by exceptions + * @deprecated Use {@link LimitExtent#LimitExtent(Extent, FaweLimit, Consumer, boolean)} */ + @Deprecated(forRemoval = true, since = "TODO") public LimitExtent(Extent extent, FaweLimit limit, Consumer onErrorMessage) { + this(extent, limit, onErrorMessage, false); + } + + /** + * Create a new instance. + * + * @param extent the extent + * @param limit the limit + * @param onErrorMessage consumer to handle a component generated by exceptions + * @param processing if this limit extent is expected to be processing + * @since TODO + */ + public LimitExtent( + Extent extent, + FaweLimit limit, + Consumer onErrorMessage, + boolean processing + ) { super(extent); this.limit = limit; this.onErrorMessage = onErrorMessage; + this.chunk_size = 16 * 16 * (extent.getMaxY() - extent.getMinY()); + this.processing = processing; } private void handleException(FaweException e) { @@ -81,7 +110,7 @@ public class LimitExtent extends AbstractDelegateExtent { public List getEntities(Region region) { limit.THROW_MAX_CHECKS(region.getVolume()); try { - return super.getEntities(region); + return extent.getEntities(region); } catch (FaweException e) { handleException(e); return Collections.emptyList(); @@ -92,7 +121,7 @@ public class LimitExtent extends AbstractDelegateExtent { public List getEntities() { limit.THROW_MAX_CHECKS(); try { - return super.getEntities(); + return extent.getEntities(); } catch (FaweException e) { handleException(e); return Collections.emptyList(); @@ -105,7 +134,7 @@ public class LimitExtent extends AbstractDelegateExtent { limit.THROW_MAX_CHANGES(); limit.THROW_MAX_ENTITIES(); try { - return super.createEntity(location, entity); + return extent.createEntity(location, entity); } catch (FaweException e) { handleException(e); return null; @@ -118,7 +147,7 @@ public class LimitExtent extends AbstractDelegateExtent { limit.THROW_MAX_CHANGES(); limit.THROW_MAX_ENTITIES(); try { - return super.createEntity(location, entity, uuid); + return extent.createEntity(location, entity, uuid); } catch (FaweException e) { handleException(e); return null; @@ -130,7 +159,7 @@ public class LimitExtent extends AbstractDelegateExtent { limit.THROW_MAX_CHANGES(); limit.THROW_MAX_ENTITIES(); try { - super.removeEntity(x, y, z, uuid); + extent.removeEntity(x, y, z, uuid); } catch (FaweException e) { handleException(e); } @@ -138,9 +167,9 @@ public class LimitExtent extends AbstractDelegateExtent { @Override public boolean regenerateChunk(int x, int z, @Nullable BiomeType type, @Nullable Long seed) { - limit.THROW_MAX_CHANGES(Character.MAX_VALUE); + limit.THROW_MAX_CHANGES(chunk_size); try { - return super.regenerateChunk(x, z, type, seed); + return extent.regenerateChunk(x, z, type, seed); } catch (FaweException e) { handleException(e); return false; @@ -151,7 +180,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getHighestTerrainBlock(int x, int z, int minY, int maxY) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getHighestTerrainBlock(x, z, minY, maxY); + return extent.getHighestTerrainBlock(x, z, minY, maxY); } catch (FaweException e) { handleException(e); return minY; @@ -162,7 +191,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getHighestTerrainBlock(int x, int z, int minY, int maxY, Mask filter) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getHighestTerrainBlock(x, z, minY, maxY, filter); + return extent.getHighestTerrainBlock(x, z, minY, maxY, filter); } catch (FaweException e) { handleException(e); return minY; @@ -173,7 +202,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getNearestSurfaceLayer(x, z, y, minY, maxY); + return extent.getNearestSurfaceLayer(x, z, y, minY, maxY); } catch (FaweException e) { handleException(e); return minY; @@ -184,7 +213,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, boolean ignoreAir) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir); + return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir); } catch (FaweException e) { handleException(e); return minY; @@ -195,7 +224,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY); + return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY); } catch (FaweException e) { handleException(e); return minY; @@ -206,7 +235,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax); + return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax); } catch (FaweException e) { handleException(e); return minY; @@ -217,7 +246,7 @@ public class LimitExtent extends AbstractDelegateExtent { public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, Mask mask) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask); + return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask); } catch (FaweException e) { handleException(e); return minY; @@ -237,91 +266,47 @@ public class LimitExtent extends AbstractDelegateExtent { ) { limit.THROW_MAX_CHECKS(maxY - minY + 1); try { - return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir); + return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir); } catch (FaweException e) { handleException(e); return minY; } } - @Override - public void addCaves(Region region) throws WorldEditException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - super.addCaves(region); - } - - @Override - public void generate(Region region, GenBase gen) throws WorldEditException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - super.generate(region, gen); - } - - @Override - public void addSchems(Region region, Mask mask, List clipboards, int rarity, boolean rotate) throws - WorldEditException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - super.addSchems(region, mask, clipboards, rarity, rotate); - } - - @Override - public void spawnResource(Region region, Resource gen, int rarity, int frequency) throws WorldEditException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - super.spawnResource(region, gen, rarity, frequency); - } - - @Override - public void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws - WorldEditException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - super.addOre(region, mask, material, size, frequency, rarity, minY, maxY); - } - - @Override - public void addOres(Region region, Mask mask) throws WorldEditException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - super.addOres(region, mask); - } - @Override public List> getBlockDistribution(Region region) { limit.THROW_MAX_CHECKS(region.getVolume()); - return super.getBlockDistribution(region); + return extent.getBlockDistribution(region); } @Override public List> getBlockDistributionWithData(Region region) { limit.THROW_MAX_CHECKS(region.getVolume()); - return super.getBlockDistributionWithData(region); + return extent.getBlockDistributionWithData(region); } @Override public int countBlocks(Region region, Set searchBlocks) { limit.THROW_MAX_CHECKS(region.getVolume()); - return super.countBlocks(region, searchBlocks); + return extent.countBlocks(region, searchBlocks); } @Override public int countBlocks(Region region, Mask searchMask) { limit.THROW_MAX_CHECKS(region.getVolume()); - return super.countBlocks(region, searchMask); + return extent.countBlocks(region, searchMask); } @Override public > int setBlocks(Region region, B block) throws MaxChangedBlocksException { limit.THROW_MAX_CHANGES(region.getVolume()); - return super.setBlocks(region, block); + return extent.setBlocks(region, block); } @Override public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { limit.THROW_MAX_CHANGES(region.getVolume()); - return super.setBlocks(region, pattern); + return extent.setBlocks(region, pattern); } @Override @@ -329,41 +314,34 @@ public class LimitExtent extends AbstractDelegateExtent { MaxChangedBlocksException { limit.THROW_MAX_CHECKS(region.getVolume()); limit.THROW_MAX_CHANGES(region.getVolume()); - return super.replaceBlocks(region, filter, replacement); + return extent.replaceBlocks(region, filter, replacement); } @Override public int replaceBlocks(Region region, Set filter, Pattern pattern) throws MaxChangedBlocksException { limit.THROW_MAX_CHECKS(region.getVolume()); limit.THROW_MAX_CHANGES(region.getVolume()); - return super.replaceBlocks(region, filter, pattern); + return extent.replaceBlocks(region, filter, pattern); } @Override public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException { limit.THROW_MAX_CHECKS(region.getVolume()); limit.THROW_MAX_CHANGES(region.getVolume()); - return super.replaceBlocks(region, mask, pattern); - } - - @Override - public int center(Region region, Pattern pattern) throws MaxChangedBlocksException { - limit.THROW_MAX_CHECKS(region.getVolume()); - limit.THROW_MAX_CHANGES(region.getVolume()); - return super.center(region, pattern); + return extent.replaceBlocks(region, mask, pattern); } @Override public int setBlocks(Set vset, Pattern pattern) { limit.THROW_MAX_CHANGES(vset.size()); - return super.setBlocks(vset, pattern); + return extent.setBlocks(vset, pattern); } @Override public T apply(Region region, T filter, boolean full) { limit.THROW_MAX_CHECKS(region.getVolume()); limit.THROW_MAX_CHANGES(region.getVolume()); - return super.apply(region, filter, full); + return extent.apply(region, filter, full); } @Override @@ -393,14 +371,14 @@ public class LimitExtent extends AbstractDelegateExtent { } limit.THROW_MAX_CHECKS(size); limit.THROW_MAX_CHANGES(size); - return super.apply(positions, filter); + return extent.apply(positions, filter); } @Override public BlockState getBlock(BlockVector3 position) { limit.THROW_MAX_CHECKS(); try { - return super.getBlock(position); + return extent.getBlock(position); } catch (FaweException e) { handleException(e); return BlockTypes.AIR.getDefaultState(); @@ -411,7 +389,7 @@ public class LimitExtent extends AbstractDelegateExtent { public BlockState getBlock(int x, int y, int z) { limit.THROW_MAX_CHECKS(); try { - return super.getBlock(x, y, z); + return extent.getBlock(x, y, z); } catch (FaweException e) { handleException(e); return BlockTypes.AIR.getDefaultState(); @@ -422,7 +400,7 @@ public class LimitExtent extends AbstractDelegateExtent { public BaseBlock getFullBlock(BlockVector3 position) { limit.THROW_MAX_CHECKS(); try { - return super.getFullBlock(position); + return extent.getFullBlock(position); } catch (FaweException e) { handleException(e); return BlockTypes.AIR.getDefaultState().toBaseBlock(); @@ -433,7 +411,7 @@ public class LimitExtent extends AbstractDelegateExtent { public BaseBlock getFullBlock(int x, int y, int z) { limit.THROW_MAX_CHECKS(); try { - return super.getFullBlock(x, y, z); + return extent.getFullBlock(x, y, z); } catch (FaweException e) { handleException(e); return BlockTypes.AIR.getDefaultState().toBaseBlock(); @@ -444,7 +422,7 @@ public class LimitExtent extends AbstractDelegateExtent { public BiomeType getBiome(BlockVector3 position) { limit.THROW_MAX_CHECKS(); try { - return super.getBiome(position); + return extent.getBiome(position); } catch (FaweException e) { handleException(e); return BiomeTypes.FOREST; @@ -455,7 +433,7 @@ public class LimitExtent extends AbstractDelegateExtent { public BiomeType getBiomeType(int x, int y, int z) { limit.THROW_MAX_CHECKS(); try { - return super.getBiomeType(x, y, z); + return extent.getBiomeType(x, y, z); } catch (FaweException e) { handleException(e); return BiomeTypes.FOREST; @@ -470,7 +448,7 @@ public class LimitExtent extends AbstractDelegateExtent { limit.THROW_MAX_BLOCKSTATES(); } try { - return super.setBlock(position, block); + return extent.setBlock(position, block); } catch (FaweException e) { handleException(e); return false; @@ -484,7 +462,7 @@ public class LimitExtent extends AbstractDelegateExtent { limit.THROW_MAX_BLOCKSTATES(); } try { - return super.setBlock(x, y, z, block); + return extent.setBlock(x, y, z, block); } catch (FaweException e) { handleException(e); return false; @@ -494,9 +472,9 @@ public class LimitExtent extends AbstractDelegateExtent { @Override public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { limit.THROW_MAX_CHANGES(); - limit.MAX_BLOCKSTATES(); + limit.THROW_MAX_BLOCKSTATES(); try { - return super.setTile(x, y, z, tile); + return extent.setTile(x, y, z, tile); } catch (FaweException e) { handleException(e); return false; @@ -507,7 +485,7 @@ public class LimitExtent extends AbstractDelegateExtent { public boolean setBiome(BlockVector3 position, BiomeType biome) { limit.THROW_MAX_CHANGES(); try { - return super.setBiome(position, biome); + return extent.setBiome(position, biome); } catch (FaweException e) { handleException(e); return false; @@ -518,11 +496,41 @@ public class LimitExtent extends AbstractDelegateExtent { public boolean setBiome(int x, int y, int z, BiomeType biome) { limit.THROW_MAX_CHANGES(); try { - return super.setBiome(x, y, z, biome); + return extent.setBiome(x, y, z, biome); } catch (FaweException e) { handleException(e); return false; } } + public void setProcessing(boolean processing) { + this.processing = processing; + } + + @Override + public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { + if (!processing) { + return set; + } + int tiles = set.getTiles().size(); + int ents = set.getEntities().size() + set.getEntityRemoves().size(); + limit.THROW_MAX_CHANGES(tiles + ents); + limit.THROW_MAX_BLOCKSTATES(tiles); + limit.THROW_MAX_ENTITIES(ents); + return set; + } + + @Override + public Extent construct(final Extent child) { + if (extent != child) { + new ExtentTraverser(this).setNext(child); + } + return this; + } + + @Override + public ProcessorScope getScope() { + return ProcessorScope.READING_SET_BLOCKS; + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java index cafd4513a..718171efd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java @@ -9,7 +9,6 @@ import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.implementation.Flood; import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; -import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ABlockMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ABlockMask.java index 7fdebdded..ed5b028dd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ABlockMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/ABlockMask.java @@ -26,7 +26,7 @@ public abstract class ABlockMask extends AbstractExtentMask { @Override public boolean test(BlockVector3 vector) { - return test(getExtent().getBlock(vector)); + return test(vector.getBlock(getExtent())); } public abstract boolean test(BlockState state); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/DataMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/DataMask.java index 2b3ad7edb..84b8f77ad 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/DataMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/DataMask.java @@ -16,9 +16,9 @@ public class DataMask extends AbstractExtentMask implements ResettableMask { @Override public boolean test(BlockVector3 vector) { if (data != -1) { - return getExtent().getBlock(vector).getInternalPropertiesId() == data; + return vector.getBlock(getExtent()).getInternalPropertiesId() == data; } else { - data = getExtent().getBlock(vector).getInternalPropertiesId(); + data = vector.getBlock(getExtent()).getInternalPropertiesId(); return true; } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/IdMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/IdMask.java index 49c90183a..b0ba4fb59 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/IdMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/IdMask.java @@ -24,7 +24,9 @@ public class IdMask extends AbstractExtentMask implements ResettableMask { @Override public boolean test(BlockVector3 vector) { - return test(getExtent(), vector); + int blockID = vector.getBlock(getExtent()).getInternalBlockTypeId(); + int testId = id.compareAndExchange(-1, blockID); + return blockID == testId || testId == -1; } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SingleBlockStateMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SingleBlockStateMask.java index 32d853bda..400f32163 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SingleBlockStateMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SingleBlockStateMask.java @@ -30,7 +30,7 @@ public class SingleBlockStateMask extends ABlockMask { @Override public boolean test(BlockVector3 vector) { - int test = getExtent().getBlock(vector).getOrdinal(); + int test = vector.getBlock(getExtent()).getOrdinal(); return ordinal == test || isAir && test == 0; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SplatterBrushMask.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SplatterBrushMask.java index 250969616..d80399be4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SplatterBrushMask.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/mask/SplatterBrushMask.java @@ -40,7 +40,7 @@ public class SplatterBrushMask extends AbstractExtentMask { double dist = vector.distanceSq(position); synchronized (placed) { if (dist < size2 && !placed.contains(vector) && ThreadLocalRandom.current().nextInt(5) < 2 && surface.test(vector)) { - placed.add(vector); + placed.add(vector.toImmutable()); return true; } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/limit/FaweLimit.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/limit/FaweLimit.java index d17787f03..2bb002914 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/limit/FaweLimit.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/limit/FaweLimit.java @@ -5,16 +5,18 @@ import com.fastasyncworldedit.core.configuration.Settings; import java.util.Collections; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; public class FaweLimit { public int MAX_ACTIONS = 0; - public long MAX_CHANGES = 0; - public int MAX_FAILS = 0; - public long MAX_CHECKS = 0; - public int MAX_ITERATIONS = 0; - public int MAX_BLOCKSTATES = 0; - public int MAX_ENTITIES = 0; + public AtomicLong MAX_CHANGES = new AtomicLong(); + public AtomicInteger MAX_FAILS = new AtomicInteger(); + public AtomicLong MAX_CHECKS = new AtomicLong(); + public AtomicInteger MAX_ITERATIONS = new AtomicInteger(); + public AtomicInteger MAX_BLOCKSTATES = new AtomicInteger(); + public AtomicInteger MAX_ENTITIES = new AtomicInteger(); public int MAX_HISTORY = 0; public int SCHEM_FILE_SIZE_LIMIT = 0; public int SCHEM_FILE_NUM_LIMIT = 0; @@ -112,12 +114,12 @@ public class FaweLimit { MAX.SPEED_REDUCTION = 0; MAX.INVENTORY_MODE = 0; MAX.MAX_ACTIONS = 1; - MAX.MAX_CHANGES = Long.MAX_VALUE; - MAX.MAX_FAILS = Integer.MAX_VALUE; - MAX.MAX_CHECKS = Long.MAX_VALUE; - MAX.MAX_ITERATIONS = Integer.MAX_VALUE; - MAX.MAX_BLOCKSTATES = Integer.MAX_VALUE; - MAX.MAX_ENTITIES = Integer.MAX_VALUE; + MAX.MAX_CHANGES = new AtomicLong(Long.MAX_VALUE); + MAX.MAX_FAILS = new AtomicInteger(Integer.MAX_VALUE); + MAX.MAX_CHECKS = new AtomicLong(Long.MAX_VALUE); + MAX.MAX_ITERATIONS = new AtomicInteger(Integer.MAX_VALUE); + MAX.MAX_BLOCKSTATES = new AtomicInteger(Integer.MAX_VALUE); + MAX.MAX_ENTITIES = new AtomicInteger(Integer.MAX_VALUE); MAX.MAX_HISTORY = Integer.MAX_VALUE; MAX.SCHEM_FILE_NUM_LIMIT = Integer.MAX_VALUE; MAX.SCHEM_FILE_SIZE_LIMIT = Integer.MAX_VALUE; @@ -138,120 +140,144 @@ public class FaweLimit { } public boolean MAX_CHANGES() { - return MAX_CHANGES-- > 0; + return MAX_CHANGES.decrementAndGet() < 0; } public boolean MAX_FAILS() { - return MAX_FAILS-- > 0; + return MAX_FAILS.decrementAndGet() < 0; } public boolean MAX_CHECKS() { - return MAX_CHECKS-- > 0; + return MAX_CHECKS.decrementAndGet() < 0; } public boolean MAX_ITERATIONS() { - return MAX_ITERATIONS-- > 0; + return MAX_ITERATIONS.decrementAndGet() < 0; } public boolean MAX_BLOCKSTATES() { - return MAX_BLOCKSTATES-- > 0; + return MAX_BLOCKSTATES.decrementAndGet() < 0; } public boolean MAX_ENTITIES() { - return MAX_ENTITIES-- > 0; + return MAX_ENTITIES.decrementAndGet() < 0; } public void THROW_MAX_CHANGES() { - if (MAX_CHANGES-- <= 0) { + if (MAX_CHANGES.decrementAndGet() < 0) { throw FaweCache.MAX_CHANGES; } } public void THROW_MAX_FAILS() { - if (MAX_FAILS-- <= 0) { - throw FaweCache.MAX_CHECKS; + if (MAX_FAILS.decrementAndGet() < 0) { + throw FaweCache.MAX_FAILS; } } public void THROW_MAX_CHECKS() { - if (MAX_CHECKS-- <= 0) { + if (MAX_CHECKS.decrementAndGet() < 0) { throw FaweCache.MAX_CHECKS; } } public void THROW_MAX_ITERATIONS() { - if (MAX_ITERATIONS-- <= 0) { + if (MAX_ITERATIONS.decrementAndGet() < 0) { throw FaweCache.MAX_ITERATIONS; } } public void THROW_MAX_BLOCKSTATES() { - if (MAX_BLOCKSTATES-- <= 0) { + if (MAX_BLOCKSTATES.decrementAndGet() < 0) { throw FaweCache.MAX_TILES; } } public void THROW_MAX_ENTITIES() { - if (MAX_ENTITIES-- <= 0) { + if (MAX_ENTITIES.decrementAndGet() < 0) { throw FaweCache.MAX_ENTITIES; } } public void THROW_MAX_CHANGES(int amt) { - if ((MAX_CHANGES -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_CHANGES.addAndGet(-amt) < 0) { throw FaweCache.MAX_CHANGES; } } public void THROW_MAX_CHANGES(long amt) { - if ((MAX_CHANGES -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_CHANGES.addAndGet(-amt) < 0) { throw FaweCache.MAX_CHANGES; } } public void THROW_MAX_FAILS(int amt) { - if ((MAX_FAILS -= amt) <= 0) { - throw FaweCache.MAX_CHECKS; + if (amt == 0) { + return; + } + if (MAX_FAILS.addAndGet(-amt) < 0) { + throw FaweCache.MAX_FAILS; } } public void THROW_MAX_CHECKS(int amt) { - if ((MAX_CHECKS -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_CHECKS.addAndGet(-amt) < 0) { throw FaweCache.MAX_CHECKS; } } public void THROW_MAX_CHECKS(long amt) { - if ((MAX_CHECKS -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_CHECKS.addAndGet(-amt) < 0) { throw FaweCache.MAX_CHECKS; } } public void THROW_MAX_ITERATIONS(int amt) { - if ((MAX_ITERATIONS -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_ITERATIONS.addAndGet(-amt) < 0) { throw FaweCache.MAX_ITERATIONS; } } public void THROW_MAX_BLOCKSTATES(int amt) { - if ((MAX_BLOCKSTATES -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_BLOCKSTATES.addAndGet(-amt) < 0) { throw FaweCache.MAX_TILES; } } public void THROW_MAX_ENTITIES(int amt) { - if ((MAX_ENTITIES -= amt) <= 0) { + if (amt == 0) { + return; + } + if (MAX_ENTITIES.addAndGet(-amt) < 0) { throw FaweCache.MAX_ENTITIES; } } public boolean isUnlimited() { - return MAX_CHANGES == Long.MAX_VALUE - && MAX_FAILS == Integer.MAX_VALUE - && MAX_CHECKS == Long.MAX_VALUE - && MAX_ITERATIONS == Integer.MAX_VALUE - && MAX_BLOCKSTATES == Integer.MAX_VALUE - && MAX_ENTITIES == Integer.MAX_VALUE + return MAX_CHANGES.get() == Long.MAX_VALUE + && MAX_FAILS.get() == Integer.MAX_VALUE + && MAX_CHECKS.get() == Long.MAX_VALUE + && MAX_ITERATIONS.get() == Integer.MAX_VALUE + && MAX_BLOCKSTATES.get() == Integer.MAX_VALUE + && MAX_ENTITIES.get() == Integer.MAX_VALUE && MAX_HISTORY == Integer.MAX_VALUE && SCHEM_FILE_SIZE_LIMIT == Integer.MAX_VALUE && SCHEM_FILE_NUM_LIMIT == Integer.MAX_VALUE @@ -270,14 +296,30 @@ public class FaweLimit { && MAX_BUTCHER_RADIUS == Integer.MAX_VALUE; } + /** + * Get an {@link FaweLimit} representing the amount of a limit used from a given "original" limit + * + * @since TODO + */ + public FaweLimit getLimitUsed(FaweLimit originalLimit) { + FaweLimit newLimit = new FaweLimit(); + newLimit.MAX_CHANGES = new AtomicLong(originalLimit.MAX_CHANGES.get() - this.MAX_CHANGES.get()); + newLimit.MAX_FAILS = new AtomicInteger(originalLimit.MAX_FAILS.get() - this.MAX_FAILS.get()); + newLimit.MAX_CHECKS = new AtomicLong(originalLimit.MAX_CHECKS.get() - this.MAX_CHECKS.get()); + newLimit.MAX_ITERATIONS = new AtomicInteger(originalLimit.MAX_ITERATIONS.get() - this.MAX_ITERATIONS.get()); + newLimit.MAX_BLOCKSTATES = new AtomicInteger(originalLimit.MAX_BLOCKSTATES.get() - this.MAX_BLOCKSTATES.get()); + newLimit.MAX_ENTITIES = new AtomicInteger(originalLimit.MAX_ENTITIES.get() - this.MAX_ENTITIES.get()); + return newLimit; + } + public void set(FaweLimit limit) { MAX_ACTIONS = limit.MAX_ACTIONS; - MAX_CHANGES = limit.MAX_CHANGES; - MAX_BLOCKSTATES = limit.MAX_BLOCKSTATES; - MAX_CHECKS = limit.MAX_CHECKS; - MAX_ENTITIES = limit.MAX_ENTITIES; - MAX_FAILS = limit.MAX_FAILS; - MAX_ITERATIONS = limit.MAX_ITERATIONS; + MAX_CHANGES.set(limit.MAX_CHANGES.get()); + MAX_FAILS.set(limit.MAX_FAILS.get()); + MAX_CHECKS.set(limit.MAX_CHECKS.get()); + MAX_ITERATIONS.set(limit.MAX_ITERATIONS.get()); + MAX_BLOCKSTATES.set(limit.MAX_BLOCKSTATES.get()); + MAX_ENTITIES.set(limit.MAX_ENTITIES.get()); MAX_HISTORY = limit.MAX_HISTORY; SCHEM_FILE_NUM_LIMIT = limit.SCHEM_FILE_NUM_LIMIT; SCHEM_FILE_SIZE_LIMIT = limit.SCHEM_FILE_SIZE_LIMIT; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java index 6b81b61f7..faec2f9f5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java @@ -50,7 +50,7 @@ public interface IBatchProcessor { } /** - * Convert this processor into an Extent based processor instead of a queue batch based on. + * Convert this processor into an Extent based processor instead of a queue batch based one. */ @Nullable Extent construct(Extent child); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index 4f987bd7e..85fbde830 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -308,16 +308,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { * @return Limit remaining */ public FaweLimit getLimitUsed() { - FaweLimit newLimit = new FaweLimit(); - newLimit.MAX_ACTIONS = originalLimit.MAX_ACTIONS - limit.MAX_ACTIONS; - newLimit.MAX_CHANGES = originalLimit.MAX_CHANGES - limit.MAX_CHANGES; - newLimit.MAX_FAILS = originalLimit.MAX_FAILS - limit.MAX_FAILS; - newLimit.MAX_CHECKS = originalLimit.MAX_CHECKS - limit.MAX_CHECKS; - newLimit.MAX_ITERATIONS = originalLimit.MAX_ITERATIONS - limit.MAX_ITERATIONS; - newLimit.MAX_BLOCKSTATES = originalLimit.MAX_BLOCKSTATES - limit.MAX_BLOCKSTATES; - newLimit.MAX_ENTITIES = originalLimit.MAX_ENTITIES - limit.MAX_ENTITIES; - newLimit.MAX_HISTORY = limit.MAX_HISTORY; - return newLimit; + return originalLimit.getLimitUsed(limit); } /** @@ -472,7 +463,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { */ @Deprecated public long getBlockChangeLimit() { - return originalLimit.MAX_CHANGES; + return originalLimit.MAX_CHANGES.get(); } /** @@ -481,7 +472,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { * @param limit the limit (>= 0) or -1 for no limit */ public void setBlockChangeLimit(long limit) { - this.limit.MAX_CHANGES = limit; + this.limit.MAX_CHANGES.set(limit); } /** @@ -1293,8 +1284,8 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { Operations.completeBlindly(commit()); // Check fails FaweLimit used = getLimitUsed(); - if (used.MAX_FAILS > 0) { - if (used.MAX_CHANGES > 0 || used.MAX_ENTITIES > 0) { + if (used.MAX_FAILS.get() > 0) { + if (used.MAX_CHANGES.get() > 0 || used.MAX_ENTITIES.get() > 0) { actor.print(Caption.of("fawe.error.worldedit.some.fails", used.MAX_FAILS)); } else if (new ExtentTraverser<>(getExtent()).findAndGet(FaweRegionExtent.class) != null) { actor.print(Caption.of("fawe.cancel.reason.outside.region")); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java index ca6f3b6a5..26650bf9c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSessionBuilder.java @@ -635,7 +635,11 @@ public final class EditSessionBuilder { }; } if (limit != null && !limit.isUnlimited()) { - this.extent = new LimitExtent(this.extent, limit, onErrorMessage); + this.extent = new LimitExtent(this.extent, limit, onErrorMessage, placeChunks && combineStages); + // Only process if we're not necessarily going to catch tiles via Extent#setBlock, e.g. because using PQE methods + if (placeChunks && combineStages) { + queue.addProcessor((LimitExtent) this.extent); + } } this.extent = wrapExtent(this.extent, eventBus, event, EditSession.Stage.BEFORE_HISTORY); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index d82bcd463..51a03119f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -1725,6 +1725,7 @@ public class LocalSession implements TextureHolder { * @return an edit session */ public EditSession createEditSession(Actor actor) { + //FAWE start return createEditSession(actor, null); } @@ -1739,7 +1740,6 @@ public class LocalSession implements TextureHolder { } // Create an edit session - //FAWE start - we don't use the edit session builder yet EditSession editSession; EditSessionBuilder builder = WorldEdit.getInstance().newEditSessionBuilder().world(world); if (actor.isPlayer() && actor instanceof Player) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index a60968da1..1f551aefa 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -30,6 +30,7 @@ import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder; import com.sk89q.worldedit.command.util.annotation.Confirm; import com.sk89q.worldedit.command.util.annotation.Preload; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; @@ -179,6 +180,7 @@ public class BiomeCommands { ) @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected // TODO improve using filter/chunk-based-placement @Confirm(Confirm.Processor.REGION) @CommandPermissions("worldedit.biome.set") public void setBiome( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index 664e656c4..e6a211a4b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -992,15 +992,15 @@ public class BrushCommands { Expression radius, @Arg(desc = "Command to run") List input, - @Switch(name = 'p', desc = "Show any printed output") - boolean print + @Switch(name = 'h', desc = "Hide any printed output") + boolean hide ) throws WorldEditException { worldEdit.checkMaxBrushRadius( radius, context.injectedValue(Key.of(Player.class)).orElseThrow(() -> new IllegalStateException("No player")) ); String cmd = StringMan.join(input, " "); - set(context, new CommandBrush(cmd, print), "worldedit.brush.command").setSize(radius); + set(context, new CommandBrush(cmd, !hide), "worldedit.brush.command").setSize(radius); } @Command( @@ -1414,7 +1414,7 @@ public class BrushCommands { //FAWE start FaweLimit limit = Settings.settings().getLimit(player); - iterations = Math.min(limit.MAX_ITERATIONS, iterations); + iterations = Math.min(limit.MAX_ITERATIONS.get(), iterations); //FAWE end set(context, new SmoothBrush(iterations, mask), "worldedit.brush.smooth").setSize(radius); @@ -1452,7 +1452,7 @@ public class BrushCommands { //FAWE start FaweLimit limit = Settings.settings().getLimit(player); - iterations = Math.min(limit.MAX_ITERATIONS, iterations); + iterations = Math.min(limit.MAX_ITERATIONS.get(), iterations); //FAWE end set(context, new SnowSmoothBrush(iterations, snowBlockCount, mask), "worldedit.brush.snowsmooth").setSize(radius); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index 378449755..bb42e7095 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -47,6 +47,7 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.annotation.Confirm; import com.sk89q.worldedit.command.util.annotation.Preload; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; @@ -153,7 +154,7 @@ public class ClipboardCommands { ((long) max.x() - (long) min.x() + 1) * ((long) max.y() - (long) min.y() + 1) * ((long) max.z() - (long) min .z() + 1); FaweLimit limit = actor.getLimit(); - if (volume >= limit.MAX_CHECKS) { + if (volume >= limit.MAX_CHECKS.get()) { throw FaweCache.MAX_CHECKS; } session.setClipboard(null); @@ -187,7 +188,7 @@ public class ClipboardCommands { long volume = (((long) max.x() - (long) min.x() + 1) * ((long) max.y() - (long) min.y() + 1) * ((long) max.z() - (long) min .z() + 1)); FaweLimit limit = actor.getLimit(); - if (volume >= limit.MAX_CHECKS) { + if (volume >= limit.MAX_CHECKS.get()) { throw FaweCache.MAX_CHECKS; } session.setClipboard(null); @@ -260,10 +261,10 @@ public class ClipboardCommands { long volume = (((long) max.x() - (long) min.x() + 1) * ((long) max.y() - (long) min.y() + 1) * ((long) max.z() - (long) min .z() + 1)); FaweLimit limit = actor.getLimit(); - if (volume >= limit.MAX_CHECKS) { + if (volume >= limit.MAX_CHECKS.get()) { throw FaweCache.MAX_CHECKS; } - if (volume >= limit.MAX_CHANGES) { + if (volume >= limit.MAX_CHANGES.get()) { throw FaweCache.MAX_CHANGES; } session.setClipboard(null); @@ -438,6 +439,7 @@ public class ClipboardCommands { desc = "Place the clipboard's contents without applying transformations (e.g. rotate)" ) @CommandPermissions("worldedit.clipboard.place") + @SynchronousSettingExpected @Logging(PLACEMENT) public void place( Actor actor, World world, LocalSession session, final EditSession editSession, @@ -502,6 +504,7 @@ public class ClipboardCommands { desc = "Paste the clipboard's contents" ) @CommandPermissions("worldedit.clipboard.paste") + @SynchronousSettingExpected @Logging(PLACEMENT) public void paste( Actor actor, World world, LocalSession session, EditSession editSession, diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java index 4b2f98e0c..f2a3c80ed 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java @@ -38,6 +38,7 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.annotation.Confirm; import com.sk89q.worldedit.command.util.annotation.Preload; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.function.mask.Mask; @@ -104,6 +105,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.cylinder") @Logging(PLACEMENT) + @SynchronousSettingExpected public int hcyl( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to generate") @@ -152,6 +154,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.cylinder") @Logging(PLACEMENT) + @SynchronousSettingExpected public int cyl( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to generate") @@ -197,6 +200,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.cone") @Logging(PLACEMENT) + @SynchronousSettingExpected public int cone(Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to generate") Pattern pattern, @@ -243,6 +247,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.sphere") @Logging(PLACEMENT) + @SynchronousSettingExpected public int hsphere( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to generate") @@ -262,6 +267,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.sphere") @Logging(PLACEMENT) + @SynchronousSettingExpected public int sphere( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to generate") @@ -313,6 +319,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.forest") @Logging(POSITION) + @SynchronousSettingExpected public int forestGen( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The size of the forest, in blocks", def = "10") @@ -337,6 +344,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.pumpkins") @Logging(POSITION) + @SynchronousSettingExpected public int pumpkins( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The size of the patch", def = "10") @@ -357,6 +365,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.pyramid") @Logging(PLACEMENT) + @SynchronousSettingExpected public int hollowPyramid( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to set") @@ -373,6 +382,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.pyramid") @Logging(PLACEMENT) + @SynchronousSettingExpected public int pyramid( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The pattern of blocks to set") @@ -400,6 +410,7 @@ public class GenerationCommands { ) @CommandPermissions("worldedit.generation.shape") @Logging(ALL) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int generate( Actor actor, LocalSession session, EditSession editSession, @@ -486,6 +497,7 @@ public class GenerationCommands { @CommandPermissions("worldedit.generation.shape.biome") @Logging(ALL) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int generateBiome( Actor actor, LocalSession session, EditSession editSession, @@ -564,6 +576,7 @@ public class GenerationCommands { @CommandPermissions("worldedit.generation.caves") @Logging(PLACEMENT) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public void caves( Actor actor, LocalSession session, EditSession editSession, @Selection Region region, @@ -602,6 +615,7 @@ public class GenerationCommands { @CommandPermissions("worldedit.generation.ore") @Logging(PLACEMENT) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public void ores( Actor actor, @@ -621,6 +635,7 @@ public class GenerationCommands { desc = "Generate an image" ) @CommandPermissions("worldedit.generation.image") + @SynchronousSettingExpected @Logging(PLACEMENT) public void image( Actor actor, @@ -685,6 +700,7 @@ public class GenerationCommands { @CommandPermissions("worldedit.generation.ore") @Logging(PLACEMENT) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public void ore( Actor actor, @@ -719,8 +735,9 @@ public class GenerationCommands { desc = "Creates a distorted sphere" ) @Logging(PLACEMENT) + @SynchronousSettingExpected @CommandPermissions("worldedit.generation.blob") - public int blobBrush( + public int blob( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "Pattern") Pattern pattern, diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java index d1a647587..ba736e45e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.annotation.Confirm; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.inventory.BlockBag; @@ -61,6 +62,7 @@ public class HistoryCommands { desc = "Undoes the last action (from history)" ) @CommandPermissions({"worldedit.history.undo", "worldedit.history.undo.self"}) + @SynchronousSettingExpected public void undo( Actor actor, LocalSession session, @Confirm(Confirm.Processor.LIMIT) @Arg(desc = "Number of undoes to perform", def = "1") @@ -108,6 +110,7 @@ public class HistoryCommands { desc = "Redoes the last action (from history)" ) @CommandPermissions({"worldedit.history.redo", "worldedit.history.redo.self"}) + @SynchronousSettingExpected public void redo( Actor actor, LocalSession session, @Confirm(Confirm.Processor.LIMIT) @Arg(desc = "Number of redoes to perform", def = "1") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index 6a121aa02..565aecb9a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -35,6 +35,7 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.annotation.Confirm; import com.sk89q.worldedit.command.util.annotation.Preload; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.function.GroundFunction; @@ -225,6 +226,7 @@ public class RegionCommands { ) @CommandPermissions("worldedit.region.line") @Logging(REGION) + @SynchronousSettingExpected public int line( Actor actor, EditSession editSession, @Selection Region region, @@ -257,6 +259,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.curve") @Logging(REGION) @Confirm(Confirm.Processor.REGION) + @SynchronousSettingExpected public int curve( Actor actor, EditSession editSession, @Selection Region region, @@ -315,6 +318,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.overlay") @Logging(REGION) @Confirm(Confirm.Processor.REGION) + @SynchronousSettingExpected // TODO improve using filter/chunk-based-placement public int overlay( Actor actor, EditSession editSession, @Selection Region region, @Arg(desc = "The pattern of blocks to overlay") @@ -333,6 +337,7 @@ public class RegionCommands { @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) @Confirm(Confirm.Processor.REGION) + @SynchronousSettingExpected // TODO improve using filter/chunk-based-placement public void lay( Actor actor, EditSession editSession, @@ -369,6 +374,7 @@ public class RegionCommands { ) @Logging(REGION) @CommandPermissions("worldedit.region.center") + @SynchronousSettingExpected public int center( Actor actor, EditSession editSession, @Selection Region region, @Arg(desc = "The pattern of blocks to set") @@ -386,6 +392,8 @@ public class RegionCommands { @CommandPermissions("worldedit.region.naturalize") @Logging(REGION) @Confirm(Confirm.Processor.REGION) + @SynchronousSettingExpected // TODO improve using filter/chunk-based-placement + @Preload(Preload.PreloadCheck.PRELOAD) public int naturalize(Actor actor, EditSession editSession, @Selection Region region) throws WorldEditException { int affected = editSession.naturalizeCuboidBlocks(region); actor.print(Caption.of("worldedit.naturalize.naturalized", TextComponent.of(affected))); @@ -437,6 +445,7 @@ public class RegionCommands { @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) @Confirm(Confirm.Processor.REGION) + @SynchronousSettingExpected public int smooth( Actor actor, EditSession editSession, @Selection Region region, @Arg(desc = "# of iterations to perform", def = "1") @@ -452,7 +461,7 @@ public class RegionCommands { long volume = (((long) max.x() - (long) min.x() + 1) * ((long) max.y() - (long) min.y() + 1) * ((long) max.z() - (long) min .z() + 1)); FaweLimit limit = actor.getLimit(); - if (volume >= limit.MAX_CHECKS) { + if (volume >= limit.MAX_CHECKS.get()) { throw FaweCache.MAX_CHECKS; } int affected; @@ -510,6 +519,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.snowsmooth") @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int snowSmooth( Actor actor, EditSession editSession, @Selection Region region, @@ -536,6 +546,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.move") @Logging(ORIENTATION_REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int move( Actor actor, World world, EditSession editSession, LocalSession session, @@ -599,6 +610,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.fall") @Logging(ORIENTATION_REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public void fall( Actor actor, EditSession editSession, @@ -618,6 +630,7 @@ public class RegionCommands { ) @CommandPermissions("worldedit.region.stack") @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Logging(ORIENTATION_REGION) public int stack( Actor actor, World world, EditSession editSession, LocalSession session, @@ -683,6 +696,7 @@ public class RegionCommands { ) @CommandPermissions("worldedit.regen") @Logging(REGION) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) void regenerate( Actor actor, World world, LocalSession session, EditSession editSession, @@ -737,6 +751,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.deform") @Logging(ALL) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int deform( Actor actor, LocalSession session, EditSession editSession, @@ -814,6 +829,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.hollow") @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int hollow( Actor actor, EditSession editSession, @@ -848,6 +864,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.forest") @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int forest( Actor actor, EditSession editSession, @Selection Region region, @@ -869,6 +886,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.flora") @Logging(REGION) @Preload(Preload.PreloadCheck.PRELOAD) + @SynchronousSettingExpected @Confirm(Confirm.Processor.REGION) public int flora( Actor actor, EditSession editSession, @Selection Region region, diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java index b98785631..074711521 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java @@ -28,6 +28,7 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.formatting.text.TextComponent; @@ -66,6 +67,7 @@ public class SnapshotUtilCommands { ) @Logging(REGION) @CommandPermissions("worldedit.snapshots.restore") + @SynchronousSettingExpected public void restore( Actor actor, World world, LocalSession session, EditSession editSession, @Arg(name = "snapshot", desc = "The snapshot to restore", def = "") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index c81db21d8..c7c6ab9a1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -44,6 +44,7 @@ import com.sk89q.worldedit.command.util.EntityRemover; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.PrintCommandHelp; import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder; +import com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; @@ -220,6 +221,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.fill") @Logging(PLACEMENT) + @SynchronousSettingExpected public int fill( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The blocks to fill with") @@ -311,6 +313,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.fill.recursive") @Logging(PLACEMENT) + @SynchronousSettingExpected public int fillr( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The blocks to fill with") @@ -343,6 +346,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.drain") @Logging(PLACEMENT) + @SynchronousSettingExpected public int drain( Actor actor, LocalSession session, EditSession editSession, //FAWE start - we take an expression over a double @@ -373,6 +377,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.fixlava") @Logging(PLACEMENT) + @SynchronousSettingExpected public int fixLava( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius to fix in") @@ -394,6 +399,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.fixwater") @Logging(PLACEMENT) + @SynchronousSettingExpected public int fixWater( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius to fix in") @@ -415,6 +421,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.removeabove") @Logging(PLACEMENT) + @SynchronousSettingExpected public int removeAbove( Actor actor, World world, LocalSession session, EditSession editSession, @Arg(desc = "The apothem of the square to remove from", def = "1") @@ -440,6 +447,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.removebelow") @Logging(PLACEMENT) + @SynchronousSettingExpected public int removeBelow( Actor actor, World world, LocalSession session, EditSession editSession, @Arg(desc = "The apothem of the square to remove from", def = "1") @@ -465,6 +473,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.removenear") @Logging(PLACEMENT) + @SynchronousSettingExpected public int removeNear( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The mask of blocks to remove") @@ -527,6 +536,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.snow") @Logging(PLACEMENT) + @SynchronousSettingExpected public int snow( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the cylinder to snow in", def = "10") @@ -566,6 +576,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.thaw") @Logging(PLACEMENT) + @SynchronousSettingExpected public int thaw( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the cylinder to thaw in", def = "10") @@ -595,6 +606,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.green") @Logging(PLACEMENT) + @SynchronousSettingExpected public int green( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the cylinder to convert in", def = "10") @@ -629,6 +641,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.extinguish") @Logging(PLACEMENT) + @SynchronousSettingExpected public int extinguish( Actor actor, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the square to remove in", def = "") @@ -843,55 +856,6 @@ public class UtilityCommands { } } -// @Command( -// name = "/hollowr", -// desc = "Hollow out a space recursively with a pattern" -// ) -// @CommandPermissions("worldedit.hollowr") -// @Logging(PLACEMENT) -// public int hollowr( -// Actor actor, -// LocalSession session, -// EditSession editSession, -// @Arg(desc = "The radius to hollow out") Expression radiusExp, -// @ArgFlag(name = 'p', desc = "The blocks to fill with") Pattern pattern, -// @ArgFlag(name = 'm', desc = "The blocks remove", def = "") Mask mask -// ) throws WorldEditException { -// //FAWE start -// double radius = radiusExp.evaluate(); -// //FAWE end -// radius = Math.max(1, radius); -// we.checkMaxRadius(radius); -// if (mask == null) { -// Mask mask = new MaskIntersection( -// new RegionMask(new EllipsoidRegion(null, origin, Vector3.at(radius, radius, radius))), -// new BoundedHeightMask( -// Math.max(lowerBound, minY), -// Math.min(maxY, origin.getBlockY()) -// ), -// Masks.negate(new ExistingBlockMask(this)) -// ); -// } -// -// // Want to replace blocks -// BlockReplace replace = new BlockReplace(this, pattern); -// -// // Pick how we're going to visit blocks -// RecursiveVisitor visitor; -// //FAWE start - provide extent for preloading, min/max y -// if (recursive) { -// visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1), minY, maxY, this); -// } else { -// visitor = new DownwardVisitor(mask, replace, origin.getBlockY(), (int) (radius * 2 + 1), minY, maxY, this); -// } -// //FAWE end -// -// BlockVector3 pos = session.getPlacementPosition(actor); -// int affected = editSession.res(pos, pattern, radius, depth, true); -// actor.print(Caption.of("worldedit.fillr.created", TextComponent.of(affected))); -// return affected; -// } - public static List> filesToEntry(final File root, final List files, final UUID uuid) { return files.stream() .map(input -> { // Keep this functional, as transform is evaluated lazily diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java index 2d35b2226..6a9a6fd95 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockDataCyler.java @@ -89,7 +89,7 @@ public class BlockDataCyler implements DoubleActionBlockTool { Property objProp = (Property) currentProperty; BaseBlock newBlock = block.with(objProp, currentProperty.getValues().get(index)); - try (EditSession editSession = session.createEditSession(player)) { + try (EditSession editSession = session.createEditSession(player, null)) { try { editSession.setBlock(blockPoint, newBlock); player.print(Caption.of( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java index 75ef200c6..b37505d8b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BlockReplacer.java @@ -63,7 +63,7 @@ public class BlockReplacer implements DoubleActionBlockTool { ) { BlockBag bag = session.getBlockBag(player); - try (EditSession editSession = session.createEditSession(player)) { + try (EditSession editSession = session.createEditSession(player, null)) { try { BlockVector3 position = clicked.toVector().toBlockPoint(); editSession.setBlock(position, pattern); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java index b35865fb3..5cec2ec11 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/SinglePickaxe.java @@ -62,7 +62,7 @@ public class SinglePickaxe implements BlockTool { return false; } - try (EditSession editSession = session.createEditSession(player)) { + try (EditSession editSession = session.createEditSession(player, null)) { try { editSession.getSurvivalExtent().setToolUse(config.superPickaxeDrop); editSession.setBlock(blockPoint, BlockTypes.AIR.getDefaultState()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/StackTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/StackTool.java index 614bbcf32..415cade93 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/StackTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/StackTool.java @@ -59,7 +59,7 @@ public class StackTool implements BlockTool { } BlockBag bag = session.getBlockBag(player); - try (EditSession editSession = session.createEditSession(player)) { + try (EditSession editSession = session.createEditSession(player, null)) { BlockStateHolder block = editSession.getFullBlock(clicked.toVector().toBlockPoint()); try { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java index 1f52ff103..db92f6af9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/TreePlanter.java @@ -60,7 +60,7 @@ public class TreePlanter implements BlockTool { @Nullable Direction face ) { - try (EditSession editSession = session.createEditSession(player)) { + try (EditSession editSession = session.createEditSession(player, null)) { try { boolean successful = false; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/Brush.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/Brush.java index 8efe2ab77..e38ae0d99 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/Brush.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/Brush.java @@ -40,4 +40,15 @@ public interface Brush { */ void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException; + //FAWE start + /** + * If this brush is expected to set blocks synchronously, i.e. from one thread (at a time) + * + * @since TODO + */ + default boolean setsSynchronously() { + return true; + } + //FAWE end + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/ConfirmHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/ConfirmHandler.java index 067f9cfeb..5d6b66483 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/ConfirmHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/ConfirmHandler.java @@ -12,7 +12,7 @@ import java.lang.reflect.Method; import java.util.Optional; /** - * Logs called commands to a logger. + * Handles commands indicated as requiring confirmation. */ public class ConfirmHandler implements CommandCallListener { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/PreloadHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/PreloadHandler.java index 9e1dc106f..037c94e5b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/PreloadHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/PreloadHandler.java @@ -11,7 +11,7 @@ import java.lang.reflect.Method; import java.util.Optional; /** - * Logs called commands to a logger. + * Initialises preloading of chunks. */ public class PreloadHandler implements CommandCallListener { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/SynchronousSettingExpected.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/SynchronousSettingExpected.java new file mode 100644 index 000000000..3cc936fda --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/SynchronousSettingExpected.java @@ -0,0 +1,22 @@ +package com.sk89q.worldedit.command.util.annotation; + +import org.enginehub.piston.inject.InjectAnnotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Indicates it is expected that blocks will only be set synchronously, i.e. from one thread (at a time) + * + * @since TODO + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ + ElementType.METHOD +}) +@InjectAnnotation +public @interface SynchronousSettingExpected { + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/package-info.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/package-info.java index 006432a73..f7f293277 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/package-info.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/package-info.java @@ -8,6 +8,7 @@ * {@link com.sk89q.worldedit.command.util.annotation.PatternList}, * {@link com.sk89q.worldedit.command.util.annotation.Preload}, * {@link com.sk89q.worldedit.command.util.annotation.PreloadHandler}, + * {@link com.sk89q.worldedit.command.util.annotation.SynchronousSettingExpected}, * {@link com.sk89q.worldedit.command.util.annotation.Step}, * {@link com.sk89q.worldedit.command.util.annotation.Time} */ diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java index b03e4ce54..65fc7c196 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java @@ -24,6 +24,7 @@ import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extension.platform.binding.Bindings; import com.fastasyncworldedit.core.extension.platform.binding.ConsumeBindings; +import com.fastasyncworldedit.core.extension.platform.binding.EditSessionHolder; import com.fastasyncworldedit.core.extension.platform.binding.PrimitiveBindings; import com.fastasyncworldedit.core.extension.platform.binding.ProvideBindings; import com.fastasyncworldedit.core.internal.command.MethodInjector; @@ -154,7 +155,6 @@ import org.enginehub.piston.inject.MemoizingValueAccess; import org.enginehub.piston.inject.MergedValueAccess; import org.enginehub.piston.part.SubCommandPart; import org.enginehub.piston.suggestion.Suggestion; -import org.enginehub.piston.util.HelpGenerator; import org.enginehub.piston.util.ValueProvider; import javax.annotation.Nonnull; @@ -227,7 +227,6 @@ public final class PlatformCommandManager { new ConfirmHandler(), new PreloadHandler() //FAWE end - )); // setup separate from main constructor // ensures that everything is definitely assigned @@ -312,20 +311,6 @@ public final class PlatformCommandManager { } ); //FAWE start - /* - globalInjectedValues.injectValue(Key.of(EditSession.class), - context -> { - LocalSession localSession = context.injectedValue(Key.of(LocalSession.class)) - .orElseThrow(() -> new IllegalStateException("No LocalSession")); - return context.injectedValue(Key.of(Actor.class)) - .map(actor -> { - EditSession editSession = localSession.createEditSession(actor); - editSession.enableStandardMode(); - Request.request().setEditSession(editSession); - return editSession; - }); - }); - */ // TODO: Ping @MattBDev to reimplement 2020-02-04 // globalInjectedValues.injectValue(Key.of(CFICommands.CFISettings.class), // context -> context.injectedValue(Key.of(Actor.class)) @@ -866,10 +851,10 @@ public final class PlatformCommandManager { store.injectValue(Key.of(InjectedValueStore.class), ValueProvider.constant(store)); store.injectValue(Key.of(Event.class), ValueProvider.constant(event)); //FAWE start - allow giving editsessions - if (event instanceof CommandEvent) { - EditSession session = ((CommandEvent) event).getSession(); + if (event instanceof CommandEvent commandEvent) { + EditSession session = commandEvent.getSession(); if (session != null) { - store.injectValue(Key.of(EditSession.class), context -> Optional.of(session)); + store.injectValue(Key.of(EditSessionHolder.class), context -> Optional.of(new EditSessionHolder(session))); } } //FAWE end diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BiomeMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BiomeMask.java index cd3ef56d5..ab919b35f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BiomeMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BiomeMask.java @@ -94,7 +94,7 @@ public class BiomeMask extends AbstractExtentMask { @Override public boolean test(BlockVector3 vector) { - BiomeType biome = getExtent().getBiome(vector); + BiomeType biome = vector.getBiome(getExtent()); return biomes.contains(biome); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockCategoryMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockCategoryMask.java index bad9781ea..a1b869efb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockCategoryMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockCategoryMask.java @@ -46,7 +46,7 @@ public class BlockCategoryMask extends AbstractExtentMask { @Override public boolean test(BlockVector3 vector) { - return category.contains(getExtent().getBlock(vector)); + return category.contains(vector.getBlock(getExtent())); } //FAWE start diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java index 9f191a4cc..c7d3473f3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java @@ -204,7 +204,7 @@ public class BlockMask extends ABlockMask { @Override public boolean test(BlockVector3 vector) { - int test = getExtent().getBlock(vector).getOrdinal(); + int test = vector.getBlock(getExtent()).getOrdinal(); return ordinals[test] || replacesAir() && test == 0; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockStateMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockStateMask.java index ac558520c..0c563cdf7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockStateMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockStateMask.java @@ -56,7 +56,7 @@ public class BlockStateMask extends AbstractExtentMask { //FAWE start @Override public boolean test(BlockVector3 vector) { - return test(getExtent().getBlock(vector)); + return test(vector.getBlock(getExtent())); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java index 17f1419e5..c3567b6d5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java @@ -124,7 +124,7 @@ public class BlockTypeMask extends AbstractExtentMask { //FAWE start @Override public boolean test(BlockVector3 vector) { - return test(getExtent().getBlock(vector).getBlockType()); + return test(vector.getBlock(getExtent()).getBlockType()); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExistingBlockMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExistingBlockMask.java index b75a4cd1e..be62c2eae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExistingBlockMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExistingBlockMask.java @@ -41,7 +41,7 @@ public class ExistingBlockMask extends AbstractExtentMask { @Override public boolean test(BlockVector3 vector) { - return !getExtent().getBlock(vector).getBlockType().getMaterial().isAir(); + return !vector.getBlock(getExtent()).getBlockType().getMaterial().isAir(); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/InverseSingleBlockStateMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/InverseSingleBlockStateMask.java index e8b14b95a..6bb39b958 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/InverseSingleBlockStateMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/InverseSingleBlockStateMask.java @@ -29,7 +29,7 @@ public class InverseSingleBlockStateMask extends ABlockMask { @Override public boolean test(BlockVector3 vector) { - int test = getExtent().getBlock(vector).getOrdinal(); + int test = vector.getBlock(getExtent()).getOrdinal(); if (isAir && test == 0) { return false; } diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index a56d98695..fea3e7dd5 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -141,6 +141,7 @@ "fawe.error.limit.max-brush-radius": "Maximum brush radius in limit: {0}", "fawe.error.limit.max-radius": "Maximum radius in limit: {0}", "fawe.error.no-valid-on-hotbar": "No valid block types on hotbar", + "fawe.error.no-process-non-synchronous-edit": "No processor holder was found but edit is non-synchronous", "fawe.cancel.count": "Cancelled {0} edits.", "fawe.cancel.reason.confirm": "Use //confirm to execute {0}", "fawe.cancel.reason.confirm.region": "Your selection is large ({0} -> {1}, containing {3} blocks). Use //confirm to execute {2}", @@ -151,6 +152,7 @@ "fawe.cancel.reason.low.memory": "Low memory", "fawe.cancel.reason.max.changes": "Too many blocks changed", "fawe.cancel.reason.max.checks": "Too many block checks", + "fawe.cancel.reason.max.fails": "Too many fails", "fawe.cancel.reason.max.tiles": "Too many block entities", "fawe.cancel.reason.max.entities": "Too many entities", "fawe.cancel.reason.max.iterations": "Max iterations", From 7e75ce78ec2b2383659cb6a1ac1eb0eb6193a8cc Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Wed, 18 Sep 2024 23:04:56 +0200 Subject: [PATCH 36/59] Fix tile copying (#2922) --- .../clipboard/DiskOptimizedClipboard.java | 36 +++++++++---------- .../extent/clipboard/LinearClipboard.java | 4 +++ 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java index c81059ccb..dc2ba4505 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/DiskOptimizedClipboard.java @@ -10,6 +10,7 @@ import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.util.MainUtil; import com.fastasyncworldedit.core.util.NbtUtils; import com.fastasyncworldedit.core.util.ReflectionUtils; +import com.google.common.collect.Collections2; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.DoubleTag; import com.sk89q.jnbt.ListTag; @@ -30,6 +31,8 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; import org.apache.logging.log4j.Logger; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinTagType; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; @@ -66,8 +69,7 @@ public class DiskOptimizedClipboard extends LinearClipboard { private static final int VERSION_2_HEADER_SIZE = 27; // Header size of "version 2" i.e. when NBT/entities could be saved private static final Map LOCK_HOLDER_CACHE = new ConcurrentHashMap<>(); - private final HashMap nbtMap; - private final HashMap nbtMap2; + private final HashMap nbtMap; private final File file; private final int headerSize; @@ -127,7 +129,6 @@ public class DiskOptimizedClipboard extends LinearClipboard { canHaveBiomes = false; } nbtMap = new HashMap<>(); - nbtMap2 = new HashMap<>(); try { this.file = file; try { @@ -184,7 +185,6 @@ public class DiskOptimizedClipboard extends LinearClipboard { super(readSize(file, versionOverride), BlockVector3.ZERO); headerSize = getHeaderSizeOverrideFromVersion(versionOverride); nbtMap = new HashMap<>(); - nbtMap2 = new HashMap<>(); try { this.file = file; this.braf = new RandomAccessFile(file, "rw"); @@ -253,12 +253,12 @@ public class DiskOptimizedClipboard extends LinearClipboard { try (NBTInputStream nbtIS = new NBTInputStream(MainUtil.getCompressedIS(new ByteBufferInputStream(tmp)))) { Iterator iter = nbtIS.toIterator(); while (nbtCount > 0 && iter.hasNext()) { // TileEntities are stored "before" entities - CompoundTag tag = iter.next(); - int x = tag.getInt("x"); - int y = tag.getInt("y"); - int z = tag.getInt("z"); + LinCompoundTag tag = iter.next().toLinTag(); + int x = tag.getTag("x", LinTagType.intTag()).valueAsInt(); + int y = tag.getTag("y", LinTagType.intTag()).valueAsInt(); + int z = tag.getTag("z", LinTagType.intTag()).valueAsInt(); IntTriple pos = new IntTriple(x, y, z); - nbtMap.put(pos, tag); + nbtMap.put(pos, FaweCompoundTag.of(tag)); nbtCount--; } while (entitiesCount > 0 && iter.hasNext()) { @@ -564,8 +564,8 @@ public class DiskOptimizedClipboard extends LinearClipboard { ))) { if (!nbtMap.isEmpty()) { try { - for (CompoundTag tag : nbtMap.values()) { - nbtOS.writeTag(tag); + for (FaweCompoundTag tag : nbtMap.values()) { + nbtOS.writeTag(new CompoundTag(tag.linTag())); } } catch (IOException e) { e.printStackTrace(); @@ -643,7 +643,7 @@ public class DiskOptimizedClipboard extends LinearClipboard { @Override public Collection getTileEntities() { - return nbtMap.values(); + return Collections2.transform(nbtMap.values(), fct -> new CompoundTag(fct.linTag())); } public int getIndex(int x, int y, int z) { @@ -661,10 +661,10 @@ public class DiskOptimizedClipboard extends LinearClipboard { private BaseBlock toBaseBlock(BlockState state, int i) { if (state.getMaterial().hasContainer() && !nbtMap.isEmpty()) { - CompoundTag nbt; + FaweCompoundTag nbt; if (nbtMap.size() < 4) { nbt = null; - for (Map.Entry entry : nbtMap.entrySet()) { + for (Map.Entry entry : nbtMap.entrySet()) { IntTriple key = entry.getKey(); int index = getIndex(key.x(), key.y(), key.z()); if (index == i) { @@ -679,15 +679,15 @@ public class DiskOptimizedClipboard extends LinearClipboard { int x = newI - z * getWidth(); nbt = nbtMap.get(new IntTriple(x, y, z)); } - return state.toBaseBlock(nbt); + return state.toBaseBlock(nbt == null ? null : nbt.linTag()); } return state.toBaseBlock(); } private BaseBlock toBaseBlock(BlockState state, int x, int y, int z) { if (state.getMaterial().hasContainer() && !nbtMap.isEmpty()) { - CompoundTag nbt = nbtMap.get(new IntTriple(x, y, z)); - return state.toBaseBlock(nbt); + FaweCompoundTag nbt = nbtMap.get(new IntTriple(x, y, z)); + return state.toBaseBlock(nbt == null ? null : nbt.linTag()); } return state.toBaseBlock(); } @@ -715,7 +715,7 @@ public class DiskOptimizedClipboard extends LinearClipboard { @Override public boolean tile(final int x, final int y, final int z, final FaweCompoundTag tile) throws WorldEditException { - nbtMap2.put(new IntTriple(x, y, z), NbtUtils.withPosition(tile, x, y, z)); + nbtMap.put(new IntTriple(x, y, z), NbtUtils.withPosition(tile, x, y, z)); return true; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/LinearClipboard.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/LinearClipboard.java index 2e65f59ca..cc0bb07f6 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/LinearClipboard.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/LinearClipboard.java @@ -57,6 +57,10 @@ public abstract class LinearClipboard extends SimpleClipboard { */ public abstract void streamBiomes(IntValueReader task); + /** + * @deprecated will be removed as it is unused and uses outdated types + */ + @Deprecated(forRemoval = true, since = "TODO") public abstract Collection getTileEntities(); @Override From 393f80165c3bbeb1e5cef625811825140e6f5d90 Mon Sep 17 00:00:00 2001 From: Jordan Date: Thu, 19 Sep 2024 05:55:53 +0100 Subject: [PATCH 37/59] fix: add timeout to reading history from exchanger (#2920) --- .../core/history/changeset/ChangeExchangeCoordinator.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java index 2f3398a60..3c020d422 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/ChangeExchangeCoordinator.java @@ -4,6 +4,8 @@ import com.sk89q.worldedit.history.change.Change; import org.jetbrains.annotations.ApiStatus; import java.util.concurrent.Exchanger; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.function.BiConsumer; /** @@ -32,8 +34,9 @@ public class ChangeExchangeCoordinator implements AutoCloseable { .start(() -> this.runnerTask.accept(this.exchanger, new Change[length])); } try { - return exchanger.exchange(consumed); - } catch (InterruptedException e) { + // Allow a reasonable timeout in case of weirdness + return exchanger.exchange(consumed, 30, TimeUnit.SECONDS); + } catch (InterruptedException | TimeoutException e) { this.runner.interrupt(); Thread.currentThread().interrupt(); return null; From 7daafa97f03e0f79baf1996b1ad9c79f7bcfb686 Mon Sep 17 00:00:00 2001 From: Jordan Date: Fri, 20 Sep 2024 23:10:39 +0100 Subject: [PATCH 38/59] fix: adjust linked filter to be left-right and do not link to new forked instances (#2913) * fix: adjust linked filter to be left-right and do not link to new forked instances - Assume that child filters know about their own forks - fixes #1874 * Remove appliesChunk|Layer for now --- .../core/extent/filter/LinkedFilter.java | 83 ++++++++++++------- .../extent/filter/block/ChunkFilterBlock.java | 12 ++- .../fastasyncworldedit/core/queue/Filter.java | 36 ++++---- .../core/queue/IDelegateFilter.java | 10 --- .../core/queue/IQueueExtent.java | 6 +- .../implementation/ParallelQueueExtent.java | 3 +- .../com/sk89q/worldedit/regions/Region.java | 12 ++- 7 files changed, 93 insertions(+), 69 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/LinkedFilter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/LinkedFilter.java index a600fc180..26700ccc5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/LinkedFilter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/LinkedFilter.java @@ -1,69 +1,92 @@ package com.fastasyncworldedit.core.extent.filter; -import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; import com.fastasyncworldedit.core.internal.simd.VectorizedFilter; import com.fastasyncworldedit.core.queue.Filter; +import com.fastasyncworldedit.core.queue.IChunk; +import com.sk89q.worldedit.regions.Region; import jdk.incubator.vector.ShortVector; +import org.jetbrains.annotations.Nullable; /** - * Filter which links two Filters together for single-filter-input operations. + * Filter which links two Filters together for single-filter-input operations. Left filter is operated first. * - * @param Parent which extends Filter - * @param Child which extends Filter + * @param Left filter + * @param Right filter */ -public sealed class LinkedFilter extends DelegateFilter { +public sealed class LinkedFilter implements Filter { - private final S child; + private final L left; + private final R right; + + public LinkedFilter(L left, R right) { + this.left = left; + this.right = right; + } @SuppressWarnings({"unchecked", "rawtypes"}) // we defeated the type system - public static LinkedFilter of(T parent, S child) { - if (parent instanceof VectorizedFilter p && child instanceof VectorizedFilter c) { - return new VectorizedLinkedFilter(p, c); + public static LinkedFilter of(L left, R right) { + if (left instanceof VectorizedFilter l && right instanceof VectorizedFilter r) { + return new VectorizedLinkedFilter(l, r); } - return new LinkedFilter<>(parent, child); + return new LinkedFilter<>(left, right); } - public LinkedFilter(T parent, S child) { - super(parent); - this.child = child; + public L getLeft() { + return this.left; } - public S getChild() { - return this.child; + public R getRight() { + return this.right; + } + + @Override + public T applyChunk(T chunk, @Nullable Region region) { + chunk = getLeft().applyChunk(chunk, region); + return getRight().applyChunk(chunk, region); } @Override public void applyBlock(FilterBlock block) { - this.getParent().applyBlock(block); - this.getChild().applyBlock(block); + getLeft().applyBlock(block); + getRight().applyBlock(block); } @Override - public LinkedFilter, ? extends Filter> newInstance(Filter other) { - return new LinkedFilter<>(this, other); + public void finishChunk(IChunk chunk) { + getLeft().finishChunk(chunk); + getRight().finishChunk(chunk); } - private final static class VectorizedLinkedFilter - extends LinkedFilter implements VectorizedFilter { + @Override + public Filter fork() { + return new LinkedFilter<>(getLeft().fork(), getRight().fork()); + } - public VectorizedLinkedFilter(final T parent, final S child) { - super(parent, child); + @Override + public void join() { + getLeft().join(); + getRight().join(); + } + + private final static class VectorizedLinkedFilter + extends LinkedFilter implements VectorizedFilter { + + public VectorizedLinkedFilter(final L left, final R right) { + super(left, right); } @Override public ShortVector applyVector(final ShortVector get, final ShortVector set) { - ShortVector res = getParent().applyVector(get, set); - return getChild().applyVector(get, res); + ShortVector res = getLeft().applyVector(get, set); + return getRight().applyVector(get, res); } @Override - public LinkedFilter, Filter> newInstance(Filter other) { - if (other instanceof VectorizedFilter o) { - return new VectorizedLinkedFilter(this, o); - } - return new LinkedFilter<>(this, other); + public Filter fork() { + return new VectorizedLinkedFilter<>((L) getLeft().fork(), (R) getRight().fork()); } + } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ChunkFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ChunkFilterBlock.java index 9e11021d2..830ff9ab1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ChunkFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/ChunkFilterBlock.java @@ -83,12 +83,20 @@ public abstract class ChunkFilterBlock extends AbstractExtentFilterBlock { /** * Filter a chunk with a region / filter. */ - public synchronized final IChunkSet filter(IChunk chunk, IChunkGet get, IChunkSet set, Filter filter, Region region, boolean full) { + public synchronized final IChunkSet filter( + IChunk chunk, + IChunkGet get, + IChunkSet set, + Filter filter, + Region region, + boolean full + ) { if (region != null) { region.filter(chunk, filter, this, get, set, full); } else { for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) { - if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + //if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + if (!full && !get.hasSection(layer)) { continue; } initLayer(get, set, layer); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/Filter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/Filter.java index 366faa8c5..f308d4806 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/Filter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/Filter.java @@ -3,6 +3,7 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; import com.sk89q.worldedit.regions.Region; +import javax.annotation.Nonnull; import javax.annotation.Nullable; /** @@ -10,30 +11,29 @@ import javax.annotation.Nullable; */ public interface Filter { - /** - * Checks whether a chunk should be read. - * - * @param chunkX the x coordinate in the chunk - * @param chunkZ the z coordinate in the chunk - */ - default boolean appliesChunk( - int chunkX, - int chunkZ - ) { - return true; - } +// /** +// * Checks whether a chunk should be read. +// * +// * @param chunkX the x coordinate in the chunk +// * @param chunkZ the z coordinate in the chunk +// */ +// default boolean appliesChunk( +// int chunkX, +// int chunkZ +// ) { +// return true; +// } /** - * Do something with the IChunk
- Return null if you don't want to filter blocks
- - * Return the chunk if you do want to filter blocks
+ * Do something with the IChunk
*/ - default T applyChunk(T chunk, @Nullable Region region) { + default @Nonnull T applyChunk(T chunk, @Nullable Region region) { return chunk; } - default boolean appliesLayer(IChunk chunk, int layer) { - return true; - } +// default boolean appliesLayer(IChunk chunk, int layer) { +// return true; +// } /** * Make changes to the block here
- e.g., block.setId(...)
- Note: Performance is diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IDelegateFilter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IDelegateFilter.java index a4bb54017..1e172dd19 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IDelegateFilter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IDelegateFilter.java @@ -9,21 +9,11 @@ public interface IDelegateFilter extends Filter { Filter getParent(); - @Override - default boolean appliesChunk(int chunkX, int chunkZ) { - return getParent().appliesChunk(chunkX, chunkZ); - } - @Override default V applyChunk(V chunk, @Nullable Region region) { return getParent().applyChunk(chunk, region); } - @Override - default boolean appliesLayer(IChunk chunk, int layer) { - return getParent().appliesLayer(chunk, layer); - } - @Override default void applyBlock(FilterBlock block) { getParent().applyBlock(block); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java index ee3740411..d09b7f04b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueExtent.java @@ -140,9 +140,9 @@ public interface IQueueExtent extends Flushable, Trimable, ICh int chunkZ, boolean full ) { - if (!filter.appliesChunk(chunkX, chunkZ)) { - return block; - } +// if (!filter.appliesChunk(chunkX, chunkZ)) { +// return block; +// } T chunk = this.getOrCreateChunk(chunkX, chunkZ); T newChunk = filter.applyChunk(chunk, region); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java index f197524f3..56a238166 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java @@ -30,7 +30,6 @@ import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.world.World; @@ -227,7 +226,7 @@ public class ParallelQueueExtent extends PassthroughExtent { public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { VectorizedFilter vectorizedPattern = SimdSupport.vectorizedPattern(pattern); var filter = LinkedFilter.of(vectorizedPattern == null ? pattern : vectorizedPattern, new CountFilter()); - return this.changes = apply(region, filter, true).getChild().getTotal(); + return this.changes = apply(region, filter, true).getRight().getTotal(); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java index 085274772..c236992cf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java @@ -269,7 +269,8 @@ public interface Region extends Iterable, Cloneable, IBatchProcess int minSection = Math.max(get.getMinSectionPosition(), getMinimumY() >> 4); int maxSection = Math.min(get.getMaxSectionPosition(), getMaximumY() >> 4); for (int layer = minSection; layer <= maxSection; layer++) { - if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + //if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + if (!full && !get.hasSection(layer)) { return; } block = block.initLayer(get, set, layer); @@ -319,7 +320,8 @@ public interface Region extends Iterable, Cloneable, IBatchProcess int layer, boolean full ) { - if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + //if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + if (!full && !get.hasSection(layer)) { return; } block = block.initLayer(get, set, layer); @@ -341,7 +343,8 @@ public interface Region extends Iterable, Cloneable, IBatchProcess int maxZ, boolean full ) { - if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + //if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + if (!full && !get.hasSection(layer)) { return; } block = block.initLayer(get, set, layer); @@ -359,7 +362,8 @@ public interface Region extends Iterable, Cloneable, IBatchProcess int yEnd, boolean full ) { - if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + //if ((!full && !get.hasSection(layer)) || !filter.appliesLayer(chunk, layer)) { + if (!full && !get.hasSection(layer)) { return; } block = block.initLayer(get, set, layer); From 8e1922dfe7841575c6b6136cb706006238cfccd2 Mon Sep 17 00:00:00 2001 From: Tyler Resch Date: Sun, 22 Sep 2024 16:41:38 -0400 Subject: [PATCH 39/59] fix: apply origin to sponge v3 schematics (#2909) * fix(#2864) * Cherry-picked EngineHub/WorldEdit@cfd9eea Co-authored-by: Pierre Maurice Schwang * Allow metadata tags to be optional + default value for this.origin Co-authored-by: Pierre Maurice Schwang * Correct depth to be default of `0` Co-authored-by: Pierre Maurice Schwang --------- Co-authored-by: Pierre Maurice Schwang --- .../clipboard/io/FastSchematicReaderV3.java | 23 ++++++++++++++++++- .../io/sponge/SpongeSchematicV3Reader.java | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV3.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV3.java index 55e249740..0e48f32d0 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV3.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/clipboard/io/FastSchematicReaderV3.java @@ -41,6 +41,8 @@ import org.apache.logging.log4j.Logger; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinIntArrayTag; +import org.enginehub.linbus.tree.LinTagType; import org.jetbrains.annotations.ApiStatus; import java.io.BufferedInputStream; @@ -88,6 +90,7 @@ public class FastSchematicReaderV3 implements ClipboardReader { private VersionedDataFixer dataFixer; private BlockVector3 offset; + private BlockVector3 origin = BlockVector3.ZERO; private BlockState[] blockPalette; private BiomeType[] biomePalette; private int dataVersion = -1; @@ -137,6 +140,24 @@ public class FastSchematicReaderV3 implements ClipboardReader { this.dataVersion = this.dataInputStream.readInt(); this.dataFixer = ReaderUtil.getVersionedDataFixer(this.dataVersion, platform, platform.getDataVersion()); } + case "Metadata" -> { + LinCompoundTag metadataCompoundTag = + (LinCompoundTag) this.nbtInputStream.readTagPayload(NBTConstants.TYPE_COMPOUND, 0).toLinTag(); + + LinCompoundTag worldEditTag = metadataCompoundTag.findTag("WorldEdit", LinTagType.compoundTag()); + if (worldEditTag != null) { // allowed to be optional + LinIntArrayTag originTag = worldEditTag.findTag("Origin", LinTagType.intArrayTag()); + if (originTag != null) { // allowed to be optional + int[] parts = originTag.value(); + + if (parts.length != 3) { + throw new IOException("`Metadata > WorldEdit > Origin` int array length is invalid."); + } + + this.origin = BlockVector3.at(parts[0], parts[1], parts[2]); + } + } + } case "Offset" -> { this.dataInputStream.skipNBytes(4); // Array Length field (4 byte int) this.offset = BlockVector3.at( @@ -173,7 +194,7 @@ public class FastSchematicReaderV3 implements ClipboardReader { clipboard.setOrigin(this.offset.multiply(-1)); if (clipboard instanceof SimpleClipboard simpleClipboard && !this.offset.equals(BlockVector3.ZERO)) { - clipboard = new BlockArrayClipboard(simpleClipboard, this.offset); + clipboard = new BlockArrayClipboard(simpleClipboard, this.offset.add(this.origin)); } return clipboard; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Reader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Reader.java index 978cb8ba5..15032be82 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Reader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/sponge/SpongeSchematicV3Reader.java @@ -135,7 +135,7 @@ public class SpongeSchematicV3Reader implements ClipboardReader { Map palette = ReaderUtil.decodePalette(paletteObject, fixer); byte[] blocks = blockContainer.getTag("Data", LinTagType.byteArrayTag()).value(); - LinListTag blockEntities = blockContainer.getListTag("BlockEntities", LinTagType.compoundTag()); + LinListTag blockEntities = blockContainer.findListTag("BlockEntities", LinTagType.compoundTag()); ReaderUtil.initializeClipboardFromBlocks(clipboard, palette, blocks, blockEntities, fixer, true); } From 24c2ef2321b9895268532e2e93ce815dab445a70 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 01:14:22 +0000 Subject: [PATCH 40/59] Update dependency com.palmergames.bukkit.towny:towny to v0.100.4.3 (#2924) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3927910c9..11f6551d2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ mapmanager = "1.8.0-SNAPSHOT" griefprevention = "17.0.0" griefdefender = "2.1.0-SNAPSHOT" residence = "4.5._13.1" -towny = "0.100.4.1" +towny = "0.100.4.3" plotsquared = "7.3.10" # Third party From f22f9abf49461a929c03c33b612a9f70b50797b0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 01:15:00 +0000 Subject: [PATCH 41/59] Update dependency com.gradleup.shadow:shadow-gradle-plugin to v8.3.2 (#2923) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index b4d03430f..5735dc56c 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -23,7 +23,7 @@ val properties = Properties().also { props -> dependencies { implementation(gradleApi()) implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2") - implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.1") + implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.2") implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.2") constraints { val asmVersion = "[9.7,)" From 9ad6ff77536bc4b211a4d920ce0d503be4fc9517 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 03:11:20 +0000 Subject: [PATCH 42/59] Update plotsquared to v7.3.11 (#2926) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 11f6551d2..64ae0731e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ griefprevention = "17.0.0" griefdefender = "2.1.0-SNAPSHOT" residence = "4.5._13.1" towny = "0.100.4.3" -plotsquared = "7.3.10" +plotsquared = "7.3.11" # Third party bstats = "3.0.3" From 5ac60f0d2ed4772870dbf2f385e623cfb22e5098 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 03:11:40 +0000 Subject: [PATCH 43/59] Update dependency paperweight-userdev (#2925) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts | 2 +- worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts index 6aac6f9d9..1642d5a51 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_20_5/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.6-R0.1-SNAPSHOT/ - the().paperDevBundle("1.20.6-R0.1-20240824.093908-124") + the().paperDevBundle("1.20.6-R0.1-20240916.192025-125") compileOnly(libs.paperlib) } diff --git a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts index 4eb949758..fce133358 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.1-R0.1-SNAPSHOT/ - the().paperDevBundle("1.21.1-R0.1-20240910.023150-72") + the().paperDevBundle("1.21.1-R0.1-20240922.215204-93") compileOnly(libs.paperlib) } From b4635e85c9ab3c300644f28b7a217d89d96a831b Mon Sep 17 00:00:00 2001 From: Jordan Date: Wed, 25 Sep 2024 18:20:49 +0100 Subject: [PATCH 44/59] fix: some improvements to GET chunk writing (#2853) * fix: some improvements to GET chunk writing - ensure levelChunk is loaded before giving to copy GET - this is not necessarily guaranteed to be nonnull if two edits overlap. Whilst not advised, such an easy failure should not occur when two edits collide * Prevent writing chunk sections when FAWE is also sending packets for a chunk and vice versa - alter IntPair hashcode to be more often unique - Utilise ConcurrentHashMap for free synchronisation * Minor comment changes * Use one-per-world-instance FaweBukkitWorld to store world chunk map --- .../fawe/v1_20_R2/PaperweightGetBlocks.java | 34 ++--- .../v1_20_R2/PaperweightPlatformAdapter.java | 56 +++++---- .../PaperweightStarlightRelighter.java | 3 +- .../fawe/v1_20_R3/PaperweightGetBlocks.java | 34 ++--- .../v1_20_R3/PaperweightPlatformAdapter.java | 56 +++++---- .../PaperweightStarlightRelighter.java | 3 +- .../fawe/v1_20_R4/PaperweightGetBlocks.java | 38 +++--- .../v1_20_R4/PaperweightPlatformAdapter.java | 64 ++++++---- .../PaperweightStarlightRelighter.java | 3 +- .../fawe/v1_21_R1/PaperweightGetBlocks.java | 38 +++--- .../v1_21_R1/PaperweightPlatformAdapter.java | 65 ++++++---- .../PaperweightStarlightRelighter.java | 3 +- .../bukkit/FaweBukkitWorld.java | 67 ++++++++++ .../bukkit/adapter/NMSAdapter.java | 119 ++++++++++++++++++ .../sk89q/worldedit/bukkit/BukkitWorld.java | 4 +- .../fastasyncworldedit/core/math/IntPair.java | 4 +- 16 files changed, 425 insertions(+), 166 deletions(-) create mode 100644 worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkitWorld.java diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java index 4bcdee27d..a325bb08b 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java @@ -7,6 +7,7 @@ import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; @@ -106,6 +107,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private final ServerLevel serverLevel; private final int chunkX; private final int chunkZ; + private final IntPair chunkPos; private final int minHeight; private final int maxHeight; private final int minSectionPosition; @@ -140,6 +142,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc this.blockLight = new DataLayer[getSectionCount()]; this.biomeRegistry = serverLevel.registryAccess().registryOrThrow(BIOME); this.biomeHolderIdMap = biomeRegistry.asHolderIdMap(); + this.chunkPos = new IntPair(chunkX, chunkZ); } public int getChunkX() { @@ -425,7 +428,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); } forceLoadSections = false; - PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + LevelChunk nmsChunk = ensureLoaded(serverLevel, chunkX, chunkZ); + PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(nmsChunk) : null; if (createCopy) { if (copies.containsKey(copyKey)) { throw new IllegalStateException("Copy key already used."); @@ -433,9 +437,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc copies.put(copyKey, copy); } try { - ServerLevel nmsWorld = serverLevel; - LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); - // Remove existing tiles. Create a copy so that we can remove blocks Map chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); List beacons = null; @@ -507,6 +508,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -584,6 +587,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -649,6 +654,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData != null ? biomeData : (PalettedContainer>) existingSection.getBiomes() ); if (!PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, existingSection, newSection, @@ -722,7 +729,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { for (UUID uuid : entityRemoves) { - Entity entity = nmsWorld.getEntities().get(uuid); + Entity entity = serverLevel.getEntities().get(uuid); if (entity != null) { removeEntity(entity); } @@ -761,7 +768,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc EntityType type = EntityType.byString(id).orElse(null); if (type != null) { - Entity entity = type.create(nmsWorld); + Entity entity = type.create(serverLevel); if (entity != null) { final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(linTag); for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { @@ -770,11 +777,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); entity.setUUID(NbtUtils.uuid(nativeTag)); - if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { + if (!serverLevel.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", id, - nmsWorld.getWorld().getName(), + serverLevel.getWorld().getName(), x, y, z @@ -804,11 +811,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc final int z = blockHash.z() + bz; final BlockPos pos = new BlockPos(x, y, z); - synchronized (nmsWorld) { - BlockEntity tileEntity = nmsWorld.getBlockEntity(pos); + synchronized (serverLevel) { + BlockEntity tileEntity = serverLevel.getBlockEntity(pos); if (tileEntity == null || tileEntity.isRemoved()) { - nmsWorld.removeBlockEntity(pos); - tileEntity = nmsWorld.getBlockEntity(pos); + serverLevel.removeBlockEntity(pos); + tileEntity = serverLevel.getBlockEntity(pos); } if (tileEntity != null) { final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); @@ -827,7 +834,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc callback = null; } else { int finalMask = bitMask != 0 ? bitMask : lightUpdate ? set.getBitMask() : 0; - boolean finalLightUpdate = lightUpdate; callback = () -> { // Set Modified nmsChunk.setLightCorrect(true); // Set Modified @@ -933,7 +939,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public void send() { synchronized (sendLock) { - PaperweightPlatformAdapter.sendChunk(this, serverLevel, chunkX, chunkZ); + PaperweightPlatformAdapter.sendChunk(new IntPair(chunkX, chunkZ), serverLevel, chunkX, chunkZ); } } diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java index a56548c46..d7fab2dd6 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java @@ -7,8 +7,8 @@ import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; import com.mojang.datafixers.util.Either; import com.sk89q.worldedit.bukkit.WorldEditPlugin; @@ -243,15 +243,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } static boolean setSectionAtomic( + String worldName, + IntPair pair, LevelChunkSection[] sections, LevelChunkSection expected, LevelChunkSection value, int layer ) { - if (layer >= 0 && layer < sections.length) { - return ReflectionUtils.compareAndSet(sections, expected, value, layer); - } - return false; + return NMSAdapter.setSectionAtomic(worldName, pair, sections, expected, value, layer); } // There is no point in having a functional semaphore for paper servers. @@ -349,7 +348,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } @SuppressWarnings("deprecation") - public static void sendChunk(Object chunk, ServerLevel nmsWorld, int chunkX, int chunkZ) { + public static void sendChunk(IntPair pair, ServerLevel nmsWorld, int chunkX, int chunkZ) { ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ); if (chunkHolder == null) { return; @@ -370,26 +369,35 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { if (levelChunk == null) { return; } + StampLockHolder lockHolder = new StampLockHolder(); + NMSAdapter.beginChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); + if (lockHolder.chunkLock == null) { + return; + } MinecraftServer.getServer().execute(() -> { - ClientboundLevelChunkWithLightPacket packet; - if (PaperLib.isPaper()) { - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null, - false // last false is to not bother with x-ray - ); - } else { - // deprecated on paper - deprecation suppressed - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null - ); + try { + ClientboundLevelChunkWithLightPacket packet; + if (PaperLib.isPaper()) { + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null, + false // last false is to not bother with x-ray + ); + } else { + // deprecated on paper - deprecation suppressed + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null + ); + } + nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); + } finally { + NMSAdapter.endChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); } - nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); }); } diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighter.java index addf03867..b92835a82 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighter.java @@ -2,6 +2,7 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter; import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.queue.IQueueExtent; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; @@ -67,7 +68,7 @@ public class PaperweightStarlightRelighter extends StarlightRelighter chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); List beacons = null; @@ -507,6 +508,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -584,6 +587,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -649,6 +654,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData != null ? biomeData : (PalettedContainer>) existingSection.getBiomes() ); if (!PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, existingSection, newSection, @@ -722,7 +729,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { for (UUID uuid : entityRemoves) { - Entity entity = nmsWorld.getEntities().get(uuid); + Entity entity = serverLevel.getEntities().get(uuid); if (entity != null) { removeEntity(entity); } @@ -761,7 +768,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc EntityType type = EntityType.byString(id).orElse(null); if (type != null) { - Entity entity = type.create(nmsWorld); + Entity entity = type.create(serverLevel); if (entity != null) { final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(linTag); for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { @@ -770,11 +777,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); entity.setUUID(NbtUtils.uuid(nativeTag)); - if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { + if (!serverLevel.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", id, - nmsWorld.getWorld().getName(), + serverLevel.getWorld().getName(), x, y, z @@ -804,11 +811,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc final int z = blockHash.z() + bz; final BlockPos pos = new BlockPos(x, y, z); - synchronized (nmsWorld) { - BlockEntity tileEntity = nmsWorld.getBlockEntity(pos); + synchronized (serverLevel) { + BlockEntity tileEntity = serverLevel.getBlockEntity(pos); if (tileEntity == null || tileEntity.isRemoved()) { - nmsWorld.removeBlockEntity(pos); - tileEntity = nmsWorld.getBlockEntity(pos); + serverLevel.removeBlockEntity(pos); + tileEntity = serverLevel.getBlockEntity(pos); } if (tileEntity != null) { final net.minecraft.nbt.CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); @@ -827,7 +834,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc callback = null; } else { int finalMask = bitMask != 0 ? bitMask : lightUpdate ? set.getBitMask() : 0; - boolean finalLightUpdate = lightUpdate; callback = () -> { // Set Modified nmsChunk.setLightCorrect(true); // Set Modified @@ -932,7 +938,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public void send() { - PaperweightPlatformAdapter.sendChunk(this, serverLevel, chunkX, chunkZ); + PaperweightPlatformAdapter.sendChunk(new IntPair(chunkX, chunkZ), serverLevel, chunkX, chunkZ); } /** diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java index 76cc25e02..2c05d7466 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java @@ -7,8 +7,8 @@ import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; import com.mojang.datafixers.util.Either; import com.sk89q.worldedit.bukkit.WorldEditPlugin; @@ -243,15 +243,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } static boolean setSectionAtomic( + String worldName, + IntPair pair, LevelChunkSection[] sections, LevelChunkSection expected, LevelChunkSection value, int layer ) { - if (layer >= 0 && layer < sections.length) { - return ReflectionUtils.compareAndSet(sections, expected, value, layer); - } - return false; + return NMSAdapter.setSectionAtomic(worldName, pair, sections, expected, value, layer); } // There is no point in having a functional semaphore for paper servers. @@ -349,7 +348,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } @SuppressWarnings("deprecation") - public static void sendChunk(Object chunk, ServerLevel nmsWorld, int chunkX, int chunkZ) { + public static void sendChunk(IntPair pair, ServerLevel nmsWorld, int chunkX, int chunkZ) { ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ); if (chunkHolder == null) { return; @@ -370,26 +369,35 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { if (levelChunk == null) { return; } + StampLockHolder lockHolder = new StampLockHolder(); + NMSAdapter.beginChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); + if (lockHolder.chunkLock == null) { + return; + } MinecraftServer.getServer().execute(() -> { - ClientboundLevelChunkWithLightPacket packet; - if (PaperLib.isPaper()) { - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null, - false // last false is to not bother with x-ray - ); - } else { - // deprecated on paper - deprecation suppressed - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null - ); + try { + ClientboundLevelChunkWithLightPacket packet; + if (PaperLib.isPaper()) { + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null, + false // last false is to not bother with x-ray + ); + } else { + // deprecated on paper - deprecation suppressed + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null + ); + } + nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); + } finally { + NMSAdapter.endChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); } - nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); }); } diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightStarlightRelighter.java index d9109b4df..a1ce327f9 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightStarlightRelighter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightStarlightRelighter.java @@ -2,6 +2,7 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter; import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.queue.IQueueExtent; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; @@ -67,7 +68,7 @@ public class PaperweightStarlightRelighter extends StarlightRelighter chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); List beacons = null; @@ -508,6 +509,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -585,6 +588,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -649,7 +654,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeRegistry, biomeData != null ? biomeData : (PalettedContainer>) existingSection.getBiomes() ); - if (!PaperweightPlatformAdapter.setSectionAtomic(levelChunkSections, existingSection, + if (!PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, + levelChunkSections, + existingSection, newSection, getSectionIndex )) { @@ -721,7 +730,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { for (UUID uuid : entityRemoves) { - Entity entity = nmsWorld.getEntities().get(uuid); + Entity entity = serverLevel.getEntities().get(uuid); if (entity != null) { removeEntity(entity); } @@ -760,7 +769,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc EntityType type = EntityType.byString(id).orElse(null); if (type != null) { - Entity entity = type.create(nmsWorld); + Entity entity = type.create(serverLevel); if (entity != null) { final net.minecraft.nbt.CompoundTag tag = (net.minecraft.nbt.CompoundTag) adapter.fromNativeLin(linTag); for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { @@ -769,11 +778,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); entity.setUUID(NbtUtils.uuid(nativeTag)); - if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { + if (!serverLevel.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", id, - nmsWorld.getWorld().getName(), + serverLevel.getWorld().getName(), x, y, z @@ -803,11 +812,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc final int z = blockHash.z() + bz; final BlockPos pos = new BlockPos(x, y, z); - synchronized (nmsWorld) { - BlockEntity tileEntity = nmsWorld.getBlockEntity(pos); + synchronized (serverLevel) { + BlockEntity tileEntity = serverLevel.getBlockEntity(pos); if (tileEntity == null || tileEntity.isRemoved()) { - nmsWorld.removeBlockEntity(pos); - tileEntity = nmsWorld.getBlockEntity(pos); + serverLevel.removeBlockEntity(pos); + tileEntity = serverLevel.getBlockEntity(pos); } if (tileEntity != null) { final net.minecraft.nbt.CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); @@ -826,7 +835,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc callback = null; } else { int finalMask = bitMask != 0 ? bitMask : lightUpdate ? set.getBitMask() : 0; - boolean finalLightUpdate = lightUpdate; callback = () -> { // Set Modified nmsChunk.setLightCorrect(true); // Set Modified @@ -932,7 +940,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public void send() { synchronized (sendLock) { - PaperweightPlatformAdapter.sendChunk(this, serverLevel, chunkX, chunkZ); + PaperweightPlatformAdapter.sendChunk(new IntPair(chunkX, chunkZ), serverLevel, chunkX, chunkZ); } } diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java index df71dae8c..838a5db53 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java @@ -7,9 +7,10 @@ import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; +import com.mojang.datafixers.util.Either; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.Refraction; @@ -76,6 +77,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -241,15 +243,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } static boolean setSectionAtomic( + String worldName, + IntPair pair, LevelChunkSection[] sections, LevelChunkSection expected, LevelChunkSection value, int layer ) { - if (layer >= 0 && layer < sections.length) { - return ReflectionUtils.compareAndSet(sections, expected, value, layer); - } - return false; + return NMSAdapter.setSectionAtomic(worldName, pair, sections, expected, value, layer); } // There is no point in having a functional semaphore for paper servers. @@ -347,7 +348,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } @SuppressWarnings("deprecation") - public static void sendChunk(Object chunk, ServerLevel nmsWorld, int chunkX, int chunkZ) { + public static void sendChunk(IntPair pair, ServerLevel nmsWorld, int chunkX, int chunkZ) { ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ); if (chunkHolder == null) { return; @@ -360,32 +361,43 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { .getChunkSource() .getChunkAtIfLoadedImmediately(chunkX, chunkZ); } else { - levelChunk = chunkHolder.getTickingChunkFuture() - .getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).orElse(null); + levelChunk = ((Optional) ((Either) chunkHolder + .getTickingChunkFuture() // method is not present with new paper chunk system + .getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left()) + .orElse(null); } if (levelChunk == null) { return; } + StampLockHolder lockHolder = new StampLockHolder(); + NMSAdapter.beginChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); + if (lockHolder.chunkLock == null) { + return; + } MinecraftServer.getServer().execute(() -> { - ClientboundLevelChunkWithLightPacket packet; - if (PaperLib.isPaper()) { - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null, - false // last false is to not bother with x-ray - ); - } else { - // deprecated on paper - deprecation suppressed - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null - ); + try { + ClientboundLevelChunkWithLightPacket packet; + if (PaperLib.isPaper()) { + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null, + false // last false is to not bother with x-ray + ); + } else { + // deprecated on paper - deprecation suppressed + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null + ); + } + nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); + } finally { + NMSAdapter.endChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); } - nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); }); } diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighter.java index ae09dcc58..c7b61575c 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightStarlightRelighter.java @@ -2,6 +2,7 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter; import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.queue.IQueueExtent; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; @@ -67,7 +68,7 @@ public class PaperweightStarlightRelighter extends StarlightRelighter chunkTiles = new HashMap<>(nmsChunk.getBlockEntities()); List beacons = null; @@ -509,6 +510,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -583,6 +586,8 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeData ); if (PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, levelChunkSections, null, newSection, @@ -644,7 +649,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc biomeRegistry, biomeData != null ? biomeData : (PalettedContainer>) existingSection.getBiomes() ); - if (!PaperweightPlatformAdapter.setSectionAtomic(levelChunkSections, existingSection, + if (!PaperweightPlatformAdapter.setSectionAtomic( + serverLevel.getWorld().getName(), + chunkPos, + levelChunkSections, + existingSection, newSection, getSectionIndex )) { @@ -716,7 +725,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } if (Settings.settings().EXPERIMENTAL.REMOVE_ENTITY_FROM_WORLD_ON_CHUNK_FAIL) { for (UUID uuid : entityRemoves) { - Entity entity = nmsWorld.getEntities().get(uuid); + Entity entity = serverLevel.getEntities().get(uuid); if (entity != null) { removeEntity(entity); } @@ -755,7 +764,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc EntityType type = EntityType.byString(id).orElse(null); if (type != null) { - Entity entity = type.create(nmsWorld); + Entity entity = type.create(serverLevel); if (entity != null) { final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(linTag); for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { @@ -764,11 +773,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc entity.load(tag); entity.absMoveTo(x, y, z, yaw, pitch); entity.setUUID(NbtUtils.uuid(nativeTag)); - if (!nmsWorld.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { + if (!serverLevel.addFreshEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM)) { LOGGER.warn( "Error creating entity of type `{}` in world `{}` at location `{},{},{}`", id, - nmsWorld.getWorld().getName(), + serverLevel.getWorld().getName(), x, y, z @@ -798,11 +807,11 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc final int z = blockHash.z() + bz; final BlockPos pos = new BlockPos(x, y, z); - synchronized (nmsWorld) { - BlockEntity tileEntity = nmsWorld.getBlockEntity(pos); + synchronized (serverLevel) { + BlockEntity tileEntity = serverLevel.getBlockEntity(pos); if (tileEntity == null || tileEntity.isRemoved()) { - nmsWorld.removeBlockEntity(pos); - tileEntity = nmsWorld.getBlockEntity(pos); + serverLevel.removeBlockEntity(pos); + tileEntity = serverLevel.getBlockEntity(pos); } if (tileEntity != null) { final CompoundTag tag = (CompoundTag) adapter.fromNativeLin(nativeTag.linTag()); @@ -821,7 +830,6 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc callback = null; } else { int finalMask = bitMask != 0 ? bitMask : lightUpdate ? set.getBitMask() : 0; - boolean finalLightUpdate = lightUpdate; callback = () -> { // Set Modified nmsChunk.setLightCorrect(true); // Set Modified @@ -927,7 +935,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public void send() { synchronized (sendLock) { - PaperweightPlatformAdapter.sendChunk(this, serverLevel, chunkX, chunkZ); + PaperweightPlatformAdapter.sendChunk(new IntPair(chunkX, chunkZ), serverLevel, chunkX, chunkZ); } } diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java index b4ed7c8ae..410152251 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java @@ -8,9 +8,10 @@ import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.util.MathMan; -import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; +import com.mojang.datafixers.util.Either; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.Refraction; @@ -31,7 +32,6 @@ import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.BitStorage; -import net.minecraft.util.ExceptionCollector; import net.minecraft.util.SimpleBitStorage; import net.minecraft.util.ThreadingDetector; import net.minecraft.util.Unit; @@ -76,6 +76,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -226,15 +227,14 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } static boolean setSectionAtomic( + String worldName, + IntPair pair, LevelChunkSection[] sections, LevelChunkSection expected, LevelChunkSection value, int layer ) { - if (layer >= 0 && layer < sections.length) { - return ReflectionUtils.compareAndSet(sections, expected, value, layer); - } - return false; + return NMSAdapter.setSectionAtomic(worldName, pair, sections, expected, value, layer); } // There is no point in having a functional semaphore for paper servers. @@ -332,7 +332,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { } @SuppressWarnings("deprecation") - public static void sendChunk(Object chunk, ServerLevel nmsWorld, int chunkX, int chunkZ) { + public static void sendChunk(IntPair pair, ServerLevel nmsWorld, int chunkX, int chunkZ) { ChunkHolder chunkHolder = getPlayerChunk(nmsWorld, chunkX, chunkZ); if (chunkHolder == null) { return; @@ -345,32 +345,43 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { .getChunkSource() .getChunkAtIfLoadedImmediately(chunkX, chunkZ); } else { - levelChunk = chunkHolder.getTickingChunkFuture() - .getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).orElse(null); + levelChunk = ((Optional) ((Either) chunkHolder + .getTickingChunkFuture() // method is not present with new paper chunk system + .getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left()) + .orElse(null); } if (levelChunk == null) { return; } + StampLockHolder lockHolder = new StampLockHolder(); + NMSAdapter.beginChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); + if (lockHolder.chunkLock == null) { + return; + } MinecraftServer.getServer().execute(() -> { - ClientboundLevelChunkWithLightPacket packet; - if (PaperLib.isPaper()) { - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null, - false // last false is to not bother with x-ray - ); - } else { - // deprecated on paper - deprecation suppressed - packet = new ClientboundLevelChunkWithLightPacket( - levelChunk, - nmsWorld.getChunkSource().getLightEngine(), - null, - null - ); + try { + ClientboundLevelChunkWithLightPacket packet; + if (PaperLib.isPaper()) { + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null, + false // last false is to not bother with x-ray + ); + } else { + // deprecated on paper - deprecation suppressed + packet = new ClientboundLevelChunkWithLightPacket( + levelChunk, + nmsWorld.getChunkSource().getLightEngine(), + null, + null + ); + } + nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); + } finally { + NMSAdapter.endChunkPacketSend(nmsWorld.getWorld().getName(), pair, lockHolder); } - nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); }); } diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightStarlightRelighter.java index f9d06922e..aa7b19b39 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightStarlightRelighter.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightStarlightRelighter.java @@ -2,6 +2,7 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1; import com.fastasyncworldedit.bukkit.adapter.StarlightRelighter; import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.queue.IQueueExtent; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; @@ -70,7 +71,7 @@ public class PaperweightStarlightRelighter extends StarlightRelighter CACHE = Collections.synchronizedMap(new WeakHashMap<>()); + + private final ConcurrentHashMap SENDING_CHUNKS = new ConcurrentHashMap<>(); + + /** + * Construct the object. + * + * @param world the world + */ + private FaweBukkitWorld(final World world) { + super(world); + } + + public static FaweBukkitWorld of(World world) { + return CACHE.compute(world, (__, val) -> { + if (val == null) { + return new FaweBukkitWorld(world); + } + val.updateReference(); + return val; + }); + } + + public static FaweBukkitWorld of(String worldName) { + World world = Bukkit.getWorld(worldName); + if (world == null) { + throw new UnsupportedOperationException("Unable to find org.bukkit.World instance for " + worldName + ". Is it loaded?"); + } + return of(world); + } + + public static ConcurrentHashMap getWorldSendingChunksMap(FaweBukkitWorld world) { + return world.SENDING_CHUNKS; + } + + public static ConcurrentHashMap getWorldSendingChunksMap(String worldName) { + return of(worldName).SENDING_CHUNKS; + } + + private void updateReference() { + World world = getWorld(); + World bukkitWorld = Bukkit.getWorld(worldNameRef); + if (bukkitWorld == null) { + throw new WorldUnloadedException(worldNameRef); + } else if (bukkitWorld != world) { + worldRef = new WeakReference<>(bukkitWorld); + } + } + +} diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSAdapter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSAdapter.java index 711c0fecc..4fc00996a 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSAdapter.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSAdapter.java @@ -1,12 +1,17 @@ package com.fastasyncworldedit.bukkit.adapter; +import com.fastasyncworldedit.bukkit.FaweBukkitWorld; import com.fastasyncworldedit.core.FAWEPlatformAdapterImpl; +import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.util.MathMan; +import com.fastasyncworldedit.core.util.ReflectionUtils; import com.sk89q.worldedit.world.block.BlockTypesCache; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.StampedLock; import java.util.function.Function; public class NMSAdapter implements FAWEPlatformAdapterImpl { @@ -140,4 +145,118 @@ public class NMSAdapter implements FAWEPlatformAdapterImpl { ((BukkitGetBlocks) chunk).send(); } + /** + * Atomically set the given chunk section to the chunk section array stored in the chunk, given the expected existing chunk + * section instance at the given layer position. + *

+ * Acquires a (FAWE-implemented only) write-lock on the chunk packet lock, waiting if required before writing, then freeing + * the lock. Also sets a boolean to indicate a write is waiting and therefore reads should not occur. + *

+ * Utilises ConcurrentHashMap#compute for easy synchronisation for all of the above. Only tryWriteLock is used in blocks + * synchronised using ConcurrentHashMap methods. + * + * @since TODO + */ + protected static boolean setSectionAtomic( + String worldName, + IntPair pair, + LevelChunkSection[] sections, + LevelChunkSection expected, + LevelChunkSection value, + int layer + ) { + if (layer < 0 || layer >= sections.length) { + return false; + } + StampLockHolder holder = new StampLockHolder(); + ConcurrentHashMap chunks = FaweBukkitWorld.getWorldSendingChunksMap(worldName); + chunks.compute(pair, (k, lock) -> { + if (lock == null) { + lock = new ChunkSendLock(); + } else if (lock.writeWaiting) { + throw new IllegalStateException("Attempting to write chunk section when write is already ongoing?!"); + } + holder.stamp = lock.lock.tryWriteLock(); + holder.chunkLock = lock; + lock.writeWaiting = true; + return lock; + }); + try { + if (holder.stamp == 0) { + holder.stamp = holder.chunkLock.lock.writeLock(); + } + return ReflectionUtils.compareAndSet(sections, expected, value, layer); + } finally { + chunks = FaweBukkitWorld.getWorldSendingChunksMap(worldName); + chunks.computeIfPresent(pair, (k, lock) -> { + if (lock != holder.chunkLock) { + throw new IllegalStateException("SENDING_CHUNKS stored lock does not equal lock attempted to be unlocked?!"); + } + lock.lock.unlockWrite(holder.stamp); + lock.writeWaiting = false; + // Keep the lock, etc. in the map as we're going to be accessing again later when sending + return lock; + }); + } + } + + /** + * Called before sending a chunk packet, filling the given stamp and stampedLock arrays' zeroth indices if the chunk packet + * send should go ahead. + *

+ * Chunk packets should be sent if both of the following are met: + * - There is no more than one current packet send ongoing + * - There is no chunk section "write" waiting or ongoing, + * which are determined by the number of readers currently locking the StampedLock (i.e. the number of sends), if the + * stamped lock is currently write-locked and if the boolean for waiting write is true. + *

+ * Utilises ConcurrentHashMap#compute for easy synchronisation + * + * @since TODO + */ + protected static void beginChunkPacketSend(String worldName, IntPair pair, StampLockHolder stampedLock) { + ConcurrentHashMap chunks = FaweBukkitWorld.getWorldSendingChunksMap(worldName); + chunks.compute(pair, (k, lock) -> { + if (lock == null) { + lock = new ChunkSendLock(); + } + // Allow twice-read-locking, so if the packets have been created but not sent, we can queue another read + if (lock.writeWaiting || lock.lock.getReadLockCount() > 1 || lock.lock.isWriteLocked()) { + return lock; + } + stampedLock.stamp = lock.lock.readLock(); + stampedLock.chunkLock = lock; + return lock; + }); + } + + /** + * Releases the read lock acquired when sending a chunk packet for a chunk + * + * @since TODO + */ + protected static void endChunkPacketSend(String worldName, IntPair pair, StampLockHolder lockHolder) { + ConcurrentHashMap chunks = FaweBukkitWorld.getWorldSendingChunksMap(worldName); + chunks.computeIfPresent(pair, (k, lock) -> { + if (lock.lock != lockHolder.chunkLock.lock) { + throw new IllegalStateException("SENDING_CHUNKS stored lock does not equal lock attempted to be unlocked?!"); + } + lock.lock.unlockRead(lockHolder.stamp); + // Do not continue to store the lock if we may not need it (i.e. chunk has been sent, may not be sent again) + return null; + }); + } + + public static final class StampLockHolder { + public long stamp; + public ChunkSendLock chunkLock = null; + } + + public static final class ChunkSendLock { + + public final StampedLock lock = new StampedLock(); + public boolean writeWaiting = false; + + } + } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 55912d770..9e4da5401 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -118,9 +118,9 @@ public class BukkitWorld extends AbstractWorld { HAS_MIN_Y = temp; } - private WeakReference worldRef; + protected WeakReference worldRef; //FAWE start - private final String worldNameRef; + protected final String worldNameRef; //FAWE end private final WorldNativeAccess worldNativeAccess; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/IntPair.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/IntPair.java index f7f451e79..b5667ccef 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/IntPair.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/IntPair.java @@ -4,7 +4,9 @@ public record IntPair(int x, int z) { @Override public int hashCode() { - return (x << 16) | (z & 0xFFFF); + int i = 1664525 * x + 1013904223; + int j = 1664525 * (z ^ -559038737) + 1013904223; + return i ^ j; } @Override From 3b6e5e83c98b019b1a7acf65df71921630935711 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sat, 28 Sep 2024 21:38:52 +0200 Subject: [PATCH 45/59] Fix NBT stripping and trimming (#2929) --- .../core/extent/LimitExtent.java | 4 +- .../core/extent/StripNBTExtent.java | 92 ++++++++++--------- .../core/queue/IBatchProcessor.java | 17 ++-- .../core/queue/IBlocks.java | 2 +- .../core/util/NbtUtils.java | 15 +++ 5 files changed, 74 insertions(+), 56 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java index d43078354..0bef1afc2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java @@ -512,8 +512,8 @@ public class LimitExtent extends AbstractDelegateExtent implements IBatchProcess if (!processing) { return set; } - int tiles = set.getTiles().size(); - int ents = set.getEntities().size() + set.getEntityRemoves().size(); + int tiles = set.tiles().size(); + int ents = set.entities().size() + set.getEntityRemoves().size(); limit.THROW_MAX_CHANGES(tiles + ents); limit.THROW_MAX_BLOCKSTATES(tiles); limit.THROW_MAX_ENTITIES(ents); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java index c0b49c333..6939743d7 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java @@ -2,14 +2,12 @@ package com.fastasyncworldedit.core.extent; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; import com.fastasyncworldedit.core.math.BlockVector3ChunkMap; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.util.ExtentTraverser; -import com.google.common.collect.ImmutableMap; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; @@ -20,16 +18,17 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.NbtValued; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; +import org.enginehub.linbus.tree.LinCompoundTag; +import org.enginehub.linbus.tree.LinTag; import javax.annotation.Nullable; -import java.util.HashMap; +import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProcessor { @@ -75,79 +74,82 @@ public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProc if (!(block instanceof BaseBlock localBlock)) { return block; } - if (!localBlock.hasNbtData()) { + final LinCompoundTag nbt = localBlock.getNbt(); + if (nbt == null) { return block; } - CompoundTag nbt = localBlock.getNbtData(); - Map> value = new HashMap<>(nbt.getValue()); + LinCompoundTag.Builder nbtBuilder = nbt.toBuilder(); for (String key : strip) { - value.remove(key); + nbtBuilder.remove(key); } - return (B) localBlock.toBaseBlock(new CompoundTag(value)); + return (B) localBlock.toBaseBlock(nbtBuilder.build()); } public T stripEntityNBT(T entity) { - if (!entity.hasNbtData()) { + LinCompoundTag nbt = entity.getNbt(); + if (nbt == null) { return entity; } - CompoundTag nbt = entity.getNbtData(); - Map> value = new HashMap<>(nbt.getValue()); + LinCompoundTag.Builder nbtBuilder = nbt.toBuilder(); for (String key : strip) { - value.remove(key); + nbtBuilder.remove(key); } - entity.setNbtData(new CompoundTag(value)); + entity.setNbt(nbtBuilder.build()); return entity; } @Override public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { - Map tiles = set.getTiles(); - Set entities = set.getEntities(); + Map tiles = set.tiles(); + Collection entities = set.entities(); if (tiles.isEmpty() && entities.isEmpty()) { return set; } boolean isBv3ChunkMap = tiles instanceof BlockVector3ChunkMap; - for (final Map.Entry entry : tiles.entrySet()) { - ImmutableMap.Builder> map = ImmutableMap.builder(); - final AtomicBoolean isStripped = new AtomicBoolean(false); - entry.getValue().getValue().forEach((k, v) -> { - if (strip.contains(k.toLowerCase())) { - isStripped.set(true); - } else { - map.put(k, v); - } - }); - if (isStripped.get()) { + for (final var entry : tiles.entrySet()) { + FaweCompoundTag original = entry.getValue(); + FaweCompoundTag result = stripNbt(original); + if (original != result) { if (isBv3ChunkMap) { // Replace existing value with stripped value - tiles.put(entry.getKey(), new CompoundTag(map.build())); + tiles.put(entry.getKey(), result); } else { - entry.setValue(new CompoundTag(map.build())); + entry.setValue(result); } } } - Set stripped = new HashSet<>(); - Iterator iterator = entities.iterator(); + Set stripped = new HashSet<>(); + Iterator iterator = entities.iterator(); while (iterator.hasNext()) { - CompoundTag entity = iterator.next(); - ImmutableMap.Builder> map = ImmutableMap.builder(); - final AtomicBoolean isStripped = new AtomicBoolean(false); - entity.getValue().forEach((k, v) -> { - if (strip.contains(k.toUpperCase(Locale.ROOT))) { - isStripped.set(true); - } else { - map.put(k, v); - } - }); - if (isStripped.get()) { + FaweCompoundTag original = iterator.next(); + FaweCompoundTag result = stripNbt(original); + if (original != result) { iterator.remove(); - stripped.add(new CompoundTag(map.build())); + stripped.add(result); } } - set.getEntities().addAll(stripped); + // this relies on entities.addAll(...) not throwing an exception if empty+unmodifiable (=> stripped is empty too) + entities.addAll(stripped); return set; } + private FaweCompoundTag stripNbt( + FaweCompoundTag compoundTag + ) { + LinCompoundTag.Builder builder = LinCompoundTag.builder(); + boolean stripped = false; + for (var entry : compoundTag.linTag().value().entrySet()) { + String k = entry.getKey(); + LinTag v = entry.getValue(); + if (strip.contains(k.toLowerCase(Locale.ROOT))) { + stripped = true; + } else { + builder.put(k, v); + } + } + return stripped ? FaweCompoundTag.of(builder.build()) : compoundTag; + } + @Nullable @Override public Extent construct(final Extent child) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java index faec2f9f5..7bce208fc 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java @@ -3,15 +3,16 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor; import com.fastasyncworldedit.core.extent.processor.MultiBatchProcessor; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; -import com.sk89q.jnbt.CompoundTag; +import com.fastasyncworldedit.core.nbt.FaweCompoundTag; +import com.fastasyncworldedit.core.util.NbtUtils; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockTypesCache; import javax.annotation.Nullable; +import java.util.Collection; import java.util.Map; -import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.function.Function; @@ -156,11 +157,11 @@ public interface IBatchProcessor { */ @Deprecated(forRemoval = true, since = "2.8.4") default boolean trimNBT(IChunkSet set, Function contains) { - Set ents = set.getEntities(); + Collection ents = set.entities(); if (!ents.isEmpty()) { - ents.removeIf(ent -> !contains.apply(ent.getEntityPosition().toBlockPoint())); + ents.removeIf(ent -> !contains.apply(NbtUtils.entityPosition(ent).toBlockPoint())); } - Map tiles = set.getTiles(); + Map tiles = set.tiles(); if (!tiles.isEmpty()) { tiles.entrySet().removeIf(blockVector3CompoundTagEntry -> !contains .apply(blockVector3CompoundTagEntry.getKey())); @@ -177,11 +178,11 @@ public interface IBatchProcessor { default boolean trimNBT( IChunkSet set, Function containsEntity, Function containsTile ) { - Set ents = set.getEntities(); + Collection ents = set.entities(); if (!ents.isEmpty()) { - ents.removeIf(ent -> !containsEntity.apply(ent.getEntityPosition().toBlockPoint())); + ents.removeIf(ent -> !containsEntity.apply(NbtUtils.entityPosition(ent).toBlockPoint())); } - Map tiles = set.getTiles(); + Map tiles = set.tiles(); if (!tiles.isEmpty()) { tiles.entrySet().removeIf(blockVector3CompoundTagEntry -> !containsTile.apply(blockVector3CompoundTagEntry.getKey())); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java index bda12dbe3..3a9d71da1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java @@ -61,7 +61,7 @@ public interface IBlocks extends Trimable { @Deprecated(forRemoval = true, since = "2.11.2") default Map getTiles() { - return AdaptedMap.immutable(tiles(), pos -> pos, IBlocks::toCompoundTag); + return AdaptedMap.values(tiles(), ct -> FaweCompoundTag.of(ct.toLinTag()), IBlocks::toCompoundTag); } Map tiles(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java index ac606ab24..8b427c322 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/NbtUtils.java @@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.util; import com.fastasyncworldedit.core.nbt.FaweCompoundTag; import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.storage.InvalidFormatException; import org.enginehub.linbus.tree.LinByteTag; @@ -211,4 +212,18 @@ public final class NbtUtils { map.put("PersistentIDLSB", LinLongTag.of(uuid.getLeastSignificantBits())); } + /** + * {@return the position data of the given tag} + * + * @param compoundTag the tag to extract position information from + * @since TODO + */ + public static Vector3 entityPosition(FaweCompoundTag compoundTag) { + LinListTag pos = compoundTag.linTag().getListTag("Pos", LinTagType.doubleTag()); + double x = pos.get(0).valueAsDouble(); + double y = pos.get(1).valueAsDouble(); + double z = pos.get(2).valueAsDouble(); + return Vector3.at(x, y, z); + } + } From bf2874ef80676a71cf39dcfec5052b07f5d2c027 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sat, 28 Sep 2024 21:39:09 +0200 Subject: [PATCH 46/59] Implement vectorization of #existing and inverse masks (#2927) --- .../core/internal/simd/SimdSupport.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/SimdSupport.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/SimdSupport.java index 23d135fa6..5f2d6a711 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/SimdSupport.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/simd/SimdSupport.java @@ -2,14 +2,17 @@ package com.fastasyncworldedit.core.internal.simd; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.filter.block.DelegateFilter; +import com.fastasyncworldedit.core.function.mask.InverseMask; import com.fastasyncworldedit.core.function.mask.SingleBlockStateMask; import com.fastasyncworldedit.core.queue.Filter; +import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.InverseSingleBlockStateMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockTypesCache; import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorOperators; @@ -44,10 +47,23 @@ public class SimdSupport { return switch (mask) { case SingleBlockStateMask single -> vectorizedTargetMask(single.getBlockState().getOrdinalChar()); case InverseSingleBlockStateMask inverse -> vectorizedTargetMaskInverse(inverse.getBlockState().getOrdinalChar()); + case ExistingBlockMask ignored -> vectorizedTargetMaskNonAir(); + case InverseMask inverse -> { + final VectorizedMask base = vectorizedTargetMask(inverse.inverse()); + if (base == null) { + yield null; + } + yield (set, get) -> base.compareVector(set, get).not(); + } default -> null; }; } + private static VectorizedMask vectorizedTargetMaskNonAir() { + // everything > VOID_AIR is not air + return (set, get) -> get.compare(VectorOperators.UNSIGNED_GT, BlockTypesCache.ReservedIDs.VOID_AIR); + } + private static VectorizedMask vectorizedTargetMask(char ordinal) { return (set, get) -> get.compare(VectorOperators.EQ, (short) ordinal); } From ba8b4e4ee8bea68720f8670812c25a9752399fb2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 28 Sep 2024 19:46:04 +0000 Subject: [PATCH 47/59] Update dependency com.sk89q.worldguard:worldguard-bukkit to v7.0.12 (#2917) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 64ae0731e..26aa321e5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ snakeyaml = "2.0" # Plugins dummypermscompat = "1.10" -worldguard-bukkit = "7.0.10" +worldguard-bukkit = "7.0.12" mapmanager = "1.8.0-SNAPSHOT" griefprevention = "17.0.0" griefdefender = "2.1.0-SNAPSHOT" From be32b2264ac17599f0e2e00d31906244bbcc16be Mon Sep 17 00:00:00 2001 From: Alexander Brandes Date: Sun, 29 Sep 2024 15:20:31 +0200 Subject: [PATCH 48/59] Bundle dependency updates Signed-off-by: Alexander Brandes --- buildSrc/build.gradle.kts | 2 +- buildSrc/src/main/kotlin/CommonJavaConfig.kt | 10 +++++----- gradle/libs.versions.toml | 6 +++--- .../adapters/adapter-1_21/build.gradle.kts | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 5735dc56c..2fb7aebc2 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -24,7 +24,7 @@ dependencies { implementation(gradleApi()) implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2") implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.2") - implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.2") + implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.3") constraints { val asmVersion = "[9.7,)" implementation("org.ow2.asm:asm:$asmVersion") { diff --git a/buildSrc/src/main/kotlin/CommonJavaConfig.kt b/buildSrc/src/main/kotlin/CommonJavaConfig.kt index ea921709c..0b90d1e06 100644 --- a/buildSrc/src/main/kotlin/CommonJavaConfig.kt +++ b/buildSrc/src/main/kotlin/CommonJavaConfig.kt @@ -41,11 +41,11 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean dependencies { "compileOnly"("com.google.code.findbugs:jsr305:3.0.2") - "testImplementation"("org.junit.jupiter:junit-jupiter-api:5.10.0") - "testImplementation"("org.junit.jupiter:junit-jupiter-params:5.10.0") - "testImplementation"("org.mockito:mockito-core:5.4.0") - "testImplementation"("org.mockito:mockito-junit-jupiter:5.4.0") - "testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.10.0") + "testImplementation"("org.junit.jupiter:junit-jupiter-api:5.11.1") + "testImplementation"("org.junit.jupiter:junit-jupiter-params:5.11.1") + "testImplementation"("org.mockito:mockito-core:5.14.0") + "testImplementation"("org.mockito:mockito-junit-jupiter:5.14.0") + "testRuntimeOnly"("org.junit.jupiter:junit-jupiter-engine:5.11.1") } // Java 8 turns on doclint which we fail diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 26aa321e5..799844713 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,12 +18,12 @@ towny = "0.100.4.3" plotsquared = "7.3.11" # Third party -bstats = "3.0.3" +bstats = "3.1.0" sparsebitset = "1.3" parallelgzip = "1.0.5" adventure = "4.17.0" adventure-bukkit = "4.3.4" -checkerqual = "3.46.0" +checkerqual = "3.47.0" truezip = "6.8.4" auto-value = "1.11.0" findbugs = "3.0.2" @@ -47,7 +47,7 @@ text = "3.0.4" piston = "0.5.10" # Tests -mockito = "5.12.0" +mockito = "5.14.0" # Gradle plugins pluginyml = "0.6.0" diff --git a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts index fce133358..760b349d3 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.1-R0.1-SNAPSHOT/ - the().paperDevBundle("1.21.1-R0.1-20240922.215204-93") + the().paperDevBundle("1.21.1-R0.1-20240928.221611-107") compileOnly(libs.paperlib) } From d9171c18f2ab50fc68851eee8c70ccb2ab5414eb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 29 Sep 2024 13:32:58 +0000 Subject: [PATCH 49/59] Update dependency gradle to v8.10.2 (#2932) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/wrapper/gradle-wrapper.jar | Bin 43504 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 2c3521197d7c4586c843d1d3e9090525f1898cde..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 3990 zcmV;H4{7l5(*nQL0Kr1kzC=_KMxQY0|W5(lc#i zH*M1^P4B}|{x<+fkObwl)u#`$GxKKV&3pg*-y6R6txw)0qU|Clf9Uds3x{_-**c=7 z&*)~RHPM>Rw#Hi1R({;bX|7?J@w}DMF>dQQU2}9yj%iLjJ*KD6IEB2^n#gK7M~}6R zkH+)bc--JU^pV~7W=3{E*4|ZFpDpBa7;wh4_%;?XM-5ZgZNnVJ=vm!%a2CdQb?oTa z70>8rTb~M$5Tp!Se+4_OKWOB1LF+7gv~$$fGC95ToUM(I>vrd$>9|@h=O?eARj0MH zT4zo(M>`LWoYvE>pXvqG=d96D-4?VySz~=tPVNyD$XMshoTX(1ZLB5OU!I2OI{kb) zS8$B8Qm>wLT6diNnyJZC?yp{Kn67S{TCOt-!OonOK7$K)e-13U9GlnQXPAb&SJ0#3 z+vs~+4Qovv(%i8g$I#FCpCG^C4DdyQw3phJ(f#y*pvNDQCRZ~MvW<}fUs~PL=4??j zmhPyg<*I4RbTz|NHFE-DC7lf2=}-sGkE5e!RM%3ohM7_I^IF=?O{m*uUPH(V?gqyc(Rp?-Qu(3bBIL4Fz(v?=_Sh?LbK{nqZMD>#9D_hNhaV$0ef3@9V90|0u#|PUNTO>$F=qRhg1duaE z0`v~X3G{8RVT@kOa-pU+z8{JWyP6GF*u2e8eKr7a2t1fuqQy)@d|Qn(%YLZ62TWtoX@$nL}9?atE#Yw`rd(>cr0gY;dT9~^oL;u)zgHUvxc2I*b&ZkGM-iq=&(?kyO(3}=P! zRp=rErEyMT5UE9GjPHZ#T<`cnD)jyIL!8P{H@IU#`e8cAG5jMK zVyKw7--dAC;?-qEu*rMr$5@y535qZ6p(R#+fLA_)G~!wnT~~)|s`}&fA(s6xXN`9j zP#Fd3GBa#HeS{5&8p?%DKUyN^X9cYUc6vq}D_3xJ&d@=6j(6BZKPl?!k1?!`f3z&a zR4ZF60Mx7oBxLSxGuzA*Dy5n-d2K=+)6VMZh_0KetK|{e;E{8NJJ!)=_E~1uu=A=r zrn&gh)h*SFhsQJo!f+wKMIE;-EOaMSMB@aXRU(UcnJhZW^B^mgs|M9@5WF@s6B0p& zm#CTz)yiQCgURE{%hjxHcJ6G&>G9i`7MyftL!QQd5 z@RflRs?7)99?X`kHNt>W3l7YqscBpi*R2+fsgABor>KVOu(i(`03aytf2UA!&SC9v z!E}whj#^9~=XHMinFZ;6UOJjo=mmNaWkv~nC=qH9$s-8roGeyaW-E~SzZ3Gg>j zZ8}<320rg4=$`M0nxN!w(PtHUjeeU?MvYgWKZ6kkzABK;vMN0|U;X9abJleJA(xy<}5h5P(5 z{RzAFPvMnX2m0yH0Jn2Uo-p`daE|(O`YQiC#jB8;6bVIUf?SY(k$#C0`d6qT`>Xe0+0}Oj0=F&*D;PVe=Z<=0AGI<6$gYLwa#r` zm449x*fU;_+J>Mz!wa;T-wldoBB%&OEMJgtm#oaI60TSYCy7;+$5?q!zi5K`u66Wq zvg)Fx$s`V3Em{=OEY{3lmh_7|08ykS&U9w!kp@Ctuzqe1JFOGz6%i5}Kmm9>^=gih z?kRxqLA<3@e=}G4R_?phW{4DVr?`tPfyZSN@R=^;P;?!2bh~F1I|fB7P=V=9a6XU5 z<#0f>RS0O&rhc&nTRFOW7&QhevP0#>j0eq<1@D5yAlgMl5n&O9X|Vq}%RX}iNyRFF z7sX&u#6?E~bm~N|z&YikXC=I0E*8Z$v7PtWfjy)$e_Ez25fnR1Q=q1`;U!~U>|&YS zaOS8y!^ORmr2L4ik!IYR8@Dcx8MTC=(b4P6iE5CnrbI~7j7DmM8em$!da&D!6Xu)!vKPdLG z9f#)se|6=5yOCe)N6xDhPI!m81*dNe7u985zi%IVfOfJh69+#ag4ELzGne?o`eA`42K4T)h3S+s)5IT97%O>du- z0U54L8m4}rkRQ?QBfJ%DLssy^+a7Ajw;0&`NOTY4o;0-ivm9 zBz1C%nr_hQ)X)^QM6T1?=yeLkuG9Lf50(eH}`tFye;01&(p?8i+6h};VV-2B~qdxeC#=X z(JLlzy&fHkyi9Ksbcs~&r^%lh^2COldLz^H@X!s~mr9Dr6z!j+4?zkD@Ls7F8(t(f z9`U?P$Lmn*Y{K}aR4N&1N=?xtQ1%jqf1~pJyQ4SgBrEtR`j4lQuh7cqP49Em5cO=I zB(He2`iPN5M=Y0}h(IU$37ANTGx&|b-u1BYA*#dE(L-lptoOpo&th~E)_)y-`6kSH z3vvyVrcBwW^_XYReJ=JYd9OBQrzv;f2AQdZH#$Y{Y+Oa33M70XFI((fs;mB4e`<<{ ze4dv2B0V_?Ytsi>>g%qs*}oDGd5d(RNZ*6?7qNbdp7wP4T72=F&r?Ud#kZr8Ze5tB z_oNb7{G+(o2ajL$!69FW@jjPQ2a5C)m!MKKRirC$_VYIuVQCpf9rIms0GRDf)8AH${I`q^~5rjot@#3$2#zT2f`(N^P7Z;6(@EK$q*Jgif00I6*^ZGV+XB5uw*1R-@23yTw&WKD{s1;HTL;dO)%5i#`dc6b7;5@^{KU%N|A-$zsYw4)7LA{3`Zp>1 z-?K9_IE&z)dayUM)wd8K^29m-l$lFhi$zj0l!u~4;VGR6Y!?MAfBC^?QD53hy6VdD z@eUZIui}~L%#SmajaRq1J|#> z4m=o$vZ*34=ZWK2!QMNEcp2Lbc5N1q!lEDq(bz0b;WI9;e>l=CG9^n#ro`w>_0F$Q zfZ={2QyTkfByC&gy;x!r*NyXXbk=a%~~(#K?< zTke0HuF5{Q+~?@!KDXR|g+43$+;ab`^flS%miup_0OUTm=nIc%d5nLP)i308PIjl_YMF6cpQ__6&$n6it8K- z8PIjl_YMF6cpQ_!r)L8IivW`WdK8mBs6PXdjR2DYdK8nCs73=4j{uVadK8oNjwX|E wpAeHLsTu^*Y>Trk?aBtSQ(D-o$(D8Px^?ZI-PUB? z*1fv!{YdHme3Fc8%cR@*@zc5A_nq&2=R47Hp@$-JF4Fz*;SLw5}K^y>s-s;V!}b2i=5=M- zComP?ju>8Fe@=H@rlwe1l`J*6BTTo`9b$zjQ@HxrAhp0D#u?M~TxGC_!?ccCHCjt| zF*PgJf@kJB`|Ml}cmsyrAjO#Kjr^E5p29w+#>$C`Q|54BoDv$fQ9D?3n32P9LPMIzu?LjNqggOH=1@T{9bMn*u8(GI z!;MLTtFPHal^S>VcJdiYqX0VU|Rn@A}C1xOlxCribxes0~+n2 z6qDaIA2$?e`opx3_KW!rAgbpzU)gFdjAKXh|5w``#F0R|c)Y)Du0_Ihhz^S?k^pk% zP>9|pIDx)xHH^_~+aA=^$M!<8K~Hy(71nJGf6`HnjtS=4X4=Hk^O71oNia2V{HUCC zoN3RSBS?mZCLw;l4W4a+D8qc)XJS`pUJ5X-f^1ytxwr`@si$lAE?{4G|o; zO0l>`rr?;~c;{ZEFJ!!3=7=FdGJ?Q^xfNQh4A?i;IJ4}B+A?4olTK(fN++3CRBP97 ze~lG9h%oegkn)lpW-4F8o2`*WW0mZHwHez`ko@>U1_;EC_6ig|Drn@=DMV9YEUSCa zIf$kHei3(u#zm9I!Jf(4t`Vm1lltJ&lVHy(eIXE8sy9sUpmz%I_gA#8x^Zv8%w?r2 z{GdkX1SkzRIr>prRK@rqn9j2wG|rUvf6PJbbin=yy-TAXrguvzN8jL$hUrIXzr^s5 zVM?H4;eM-QeRFr06@ifV(ocvk?_)~N@1c2ien56UjWXid6W%6ievIh)>dk|rIs##^kY67ib8Kw%#-oVFaXG7$ERyA9(NSJUvWiOA5H(!{uOpcW zg&-?iqPhds%3%tFspHDqqr;A!e@B#iPQjHd=c>N1LoOEGRehVoPOdxJ>b6>yc#o#+ zl8s8!(|NMeqjsy@0x{8^j0d00SqRZjp{Kj)&4UHYGxG+z9b-)72I*&J70?+8e?p_@ z=>-(>l6z5vYlP~<2%DU02b!mA{7mS)NS_eLe=t)sm&+Pmk?asOEKlkPQ)EUvvfC=;4M&*|I!w}(@V_)eUKLA_t^%`o z0PM9LV|UKTLnk|?M3u!|f2S0?UqZsEIH9*NJS-8lzu;A6-rr-ot=dg9SASoluZUkFH$7X; zP=?kYX!K?JL-b~<#7wU;b;eS)O;@?h%sPPk{4xEBxb{!sm0AY|f9cNvx6>$3F!*0c z75H=dy8JvTyO8}g1w{$9T$p~5en}AeSLoCF>_RT9YPMpChUjl310o*$QocjbH& zbnwg#gssR#jDVN{uEi3n(PZ%PFZ|6J2 z5_rBf0-u>e4sFe0*Km49ATi7>Kn0f9!uc|rRMR1Dtt6m1LW8^>qFlo}h$@br=Rmpi z;mI&>OF64Be{dVeHI8utrh)v^wsZ0jii%x8UgZ8TC%K~@I(4E};GFW&(;WVov}3%H zH;IhRkfD^(vt^DjZz(MyHLZxv8}qzPc(%itBkBwf_fC~sDBgh<3XAv5cxxfF3<2U! z03Xe&z`is!JDHbe;mNmfkH+_LFE*I2^mdL@7(@9DfAcP6O04V-ko;Rpgp<%Cj5r8Z zd0`sXoIjV$j)--;jA6Zy^D5&5v$o^>e%>Q?9GLm{i~p^lAn!%ZtF$I~>39XVZxk0b zROh^Bk9cE0AJBLozZIEmy7xG(yHWGztvfnr0(2ro1%>zsGMS^EMu+S$r=_;9 zWwZkgf7Q7`H9sLf2Go^Xy6&h~a&%s2_T@_Csf19MntF$aVFiFkvE3_hUg(B@&Xw@YJ zpL$wNYf78=0c@!QU6_a$>CPiXT7QAGDM}7Z(0z#_ZA=fmLUj{2z7@Ypo71UDy8GHr z-&TLKf6a5WCf@Adle3VglBt4>Z>;xF}}-S~B7<(%B;Y z0QR55{z-buw>8ilNM3u6I+D$S%?)(p>=eBx-HpvZj{7c*_?K=d()*7q?93us}1dq%FAFYLsW8ZTQ_XZLh`P2*6(NgS}qGcfGXVWpwsp#Rs}IuKbk*`2}&) zI^Vsk6S&Q4@oYS?dJ`NwMVBs6f57+RxdqVub#PvMu?$=^OJy5xEl0<5SLsSRy%%a0 zi}Y#1-F3m;Ieh#Y12UgW?-R)|eX>ZuF-2cc!1>~NS|XSF-6In>zBoZg+ml!6%fk7U zw0LHcz8VQk(jOJ+Yu)|^|15ufl$KQd_1eUZZzj`aC%umU6F1&D5XVWce_wAe(qCSZ zpX-QF4e{EmEVN9~6%bR5U*UT{eMHfcUo`jw*u?4r2s_$`}U{?NjvEm(u&<>B|%mq$Q3weshxk z76<``8vh{+nX`@9CB6IE&z)I%IFjR^LH{s1p|eppv=x za(g_jLU|xjWMAn-V7th$f({|LG8zzIE0g?cyW;%Dmtv%C+0@xVxPE^ zyZzi9P%JAD6ynwHptuzP`Kox7*9h7XSMonCalv;Md0i9Vb-c*!f0ubfk?&T&T}AHh z4m8Bz{JllKcdNg?D^%a5MFQ;#1z|*}H^qHLzW)L}wp?2tY7RejtSh8<;Zw)QGJYUm z|MbTxyj*McKlStlT9I5XlSWtQGN&-LTr2XyNU+`490rg?LYLMRnz-@oKqT1hpCGqP zyRXt4=_Woj$%n5ee<3zhLF>5>`?m9a#xQH+Jk_+|RM8Vi;2*XbK- zEL6sCpaGPzP>k8f4Kh|##_imt#zJMB;ir|JrMPGW`rityK1vHXMLy18%qmMQAm4WZ zP)i30KR&5vs15)C+8dM66&$k~i|ZT;KR&5vs15)C+8dJ(sAmGPijyIz6_bsqKLSFH zlOd=TljEpH0>h4zA*dCTK&emy#FCRCs1=i^sZ9bFmXjf<6_X39E(XY)00000#N437 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0aaefbcaf..df97d72b8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From cc2f6459f93bf04a76704d1ceccb4173d3b3b661 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 29 Sep 2024 13:34:55 +0000 Subject: [PATCH 50/59] Update dependency org.mockito:mockito-core to v5.14.0 (#2933) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- worldedit-sponge/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-sponge/build.gradle.kts b/worldedit-sponge/build.gradle.kts index 1c3ad6b68..2c5c4d70b 100644 --- a/worldedit-sponge/build.gradle.kts +++ b/worldedit-sponge/build.gradle.kts @@ -28,7 +28,7 @@ dependencies { }) api("org.apache.logging.log4j:log4j-api") api("org.bstats:bstats-sponge:1.7") - testImplementation("org.mockito:mockito-core:5.12.0") + testImplementation("org.mockito:mockito-core:5.14.0") } <<<<<<< HEAD From 631269cafe7c1160bcfd5a431047e815349d6df1 Mon Sep 17 00:00:00 2001 From: Jordan Date: Sun, 29 Sep 2024 18:27:53 +0100 Subject: [PATCH 51/59] fix: update to changes to spigot chunk future result (#2934) --- .../impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java | 9 ++------- .../impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java index 838a5db53..e7672ce81 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java @@ -357,14 +357,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { LevelChunk levelChunk; if (PaperLib.isPaper()) { // getChunkAtIfLoadedImmediately is paper only - levelChunk = nmsWorld - .getChunkSource() - .getChunkAtIfLoadedImmediately(chunkX, chunkZ); + levelChunk = nmsWorld.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ); } else { - levelChunk = ((Optional) ((Either) chunkHolder - .getTickingChunkFuture() // method is not present with new paper chunk system - .getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left()) - .orElse(null); + levelChunk = chunkHolder.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).orElse(null); } if (levelChunk == null) { return; diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java index 410152251..662140955 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java @@ -341,14 +341,9 @@ public final class PaperweightPlatformAdapter extends NMSAdapter { LevelChunk levelChunk; if (PaperLib.isPaper()) { // getChunkAtIfLoadedImmediately is paper only - levelChunk = nmsWorld - .getChunkSource() - .getChunkAtIfLoadedImmediately(chunkX, chunkZ); + levelChunk = nmsWorld.getChunkSource().getChunkAtIfLoadedImmediately(chunkX, chunkZ); } else { - levelChunk = ((Optional) ((Either) chunkHolder - .getTickingChunkFuture() // method is not present with new paper chunk system - .getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left()) - .orElse(null); + levelChunk = chunkHolder.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK).orElse(null); } if (levelChunk == null) { return; From 7192e147d0e3e26dd77d8d5b185aeacc23823c10 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 01:32:16 +0000 Subject: [PATCH 52/59] Update dependency paperweight-userdev to v1.21.1-R0.1-20240929.223546-111 (#2935) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts index 760b349d3..feafadc70 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.1-R0.1-SNAPSHOT/ - the().paperDevBundle("1.21.1-R0.1-20240928.221611-107") + the().paperDevBundle("1.21.1-R0.1-20240929.223546-111") compileOnly(libs.paperlib) } From be3ae1afd9ffff08c82cd46a63fb34f228c18333 Mon Sep 17 00:00:00 2001 From: Pierre Maurice Schwang Date: Mon, 7 Oct 2024 01:50:12 +0200 Subject: [PATCH 53/59] fix: don't require WEOrigin / WEOffset in MCEdit schematics (#2936) --- .../clipboard/io/MCEditSchematicReader.java | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java index 945cd6981..8e54249cd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/MCEditSchematicReader.java @@ -57,6 +57,7 @@ import java.io.UncheckedIOException; import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.NoSuchElementException; import java.util.Set; /** @@ -126,18 +127,25 @@ public class MCEditSchematicReader extends NBTSchematicReader { short height = schematicTag.getTag("Height", LinTagType.shortTag()).valueAsShort(); short length = schematicTag.getTag("Length", LinTagType.shortTag()).valueAsShort(); - int originX = schematicTag.getTag("WEOriginX", LinTagType.intTag()).valueAsInt(); - int originY = schematicTag.getTag("WEOriginY", LinTagType.intTag()).valueAsInt(); - int originZ = schematicTag.getTag("WEOriginZ", LinTagType.intTag()).valueAsInt(); - BlockVector3 min = BlockVector3.at(originX, originY, originZ); + try { + int originX = schematicTag.getTag("WEOriginX", LinTagType.intTag()).valueAsInt(); + int originY = schematicTag.getTag("WEOriginY", LinTagType.intTag()).valueAsInt(); + int originZ = schematicTag.getTag("WEOriginZ", LinTagType.intTag()).valueAsInt(); + BlockVector3 min = BlockVector3.at(originX, originY, originZ); + + int offsetX = schematicTag.getTag("WEOffsetX", LinTagType.intTag()).valueAsInt(); + int offsetY = schematicTag.getTag("WEOffsetY", LinTagType.intTag()).valueAsInt(); + int offsetZ = schematicTag.getTag("WEOffsetZ", LinTagType.intTag()).valueAsInt(); + BlockVector3 offset = BlockVector3.at(offsetX, offsetY, offsetZ); + + origin = min.subtract(offset); + region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE)); + } catch (NoSuchElementException e) { + origin = BlockVector3.ZERO; + region = new CuboidRegion(origin, origin.add(width, height, length).subtract(BlockVector3.ONE)); + } - int offsetX = schematicTag.getTag("WEOffsetX", LinTagType.intTag()).valueAsInt(); - int offsetY = schematicTag.getTag("WEOffsetY", LinTagType.intTag()).valueAsInt(); - int offsetZ = schematicTag.getTag("WEOffsetZ", LinTagType.intTag()).valueAsInt(); - BlockVector3 offset = BlockVector3.at(offsetX, offsetY, offsetZ); - origin = min.subtract(offset); - region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE)); // ==================================================================== // Blocks From d58026dd045d305a76b2ddfe1357a8fc30a736da Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 01:06:05 +0000 Subject: [PATCH 54/59] Update dependency com.palmergames.bukkit.towny:towny to v0.100.4.4 (#2940) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 799844713..c27590f1a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ mapmanager = "1.8.0-SNAPSHOT" griefprevention = "17.0.0" griefdefender = "2.1.0-SNAPSHOT" residence = "4.5._13.1" -towny = "0.100.4.3" +towny = "0.100.4.4" plotsquared = "7.3.11" # Third party From 8c9074ff73d8bdfe7dc3438d17eaa2e723124555 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 03:41:59 +0000 Subject: [PATCH 55/59] Update dependency org.mockito:mockito-core to v5.14.1 (#2941) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- worldedit-sponge/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c27590f1a..a11448070 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -47,7 +47,7 @@ text = "3.0.4" piston = "0.5.10" # Tests -mockito = "5.14.0" +mockito = "5.14.1" # Gradle plugins pluginyml = "0.6.0" diff --git a/worldedit-sponge/build.gradle.kts b/worldedit-sponge/build.gradle.kts index 2c5c4d70b..fedd48c00 100644 --- a/worldedit-sponge/build.gradle.kts +++ b/worldedit-sponge/build.gradle.kts @@ -28,7 +28,7 @@ dependencies { }) api("org.apache.logging.log4j:log4j-api") api("org.bstats:bstats-sponge:1.7") - testImplementation("org.mockito:mockito-core:5.14.0") + testImplementation("org.mockito:mockito-core:5.14.1") } <<<<<<< HEAD From b343be40c8750572ed437cafdf46cc8839628167 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 03:42:32 +0000 Subject: [PATCH 56/59] Update dependency paperweight-userdev to v1.21.1-R0.1-20241003.152200-116 (#2942) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts index feafadc70..32e298776 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.1-R0.1-SNAPSHOT/ - the().paperDevBundle("1.21.1-R0.1-20240929.223546-111") + the().paperDevBundle("1.21.1-R0.1-20241003.152200-116") compileOnly(libs.paperlib) } From bdadef6511945b366d360b2c70af75050e19df30 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 13 Oct 2024 08:39:24 +0000 Subject: [PATCH 57/59] Update dependency com.gradleup.shadow:shadow-gradle-plugin to v8.3.3 (#2939) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 2fb7aebc2..f2d748d25 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -23,7 +23,7 @@ val properties = Properties().also { props -> dependencies { implementation(gradleApi()) implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2") - implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.2") + implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.3") implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.3") constraints { val asmVersion = "[9.7,)" From ced53d3ce8e8c1cd49d441a3094a8126f8b5e464 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 00:44:46 +0000 Subject: [PATCH 58/59] Update dependency org.ajoberstar.grgit:grgit-gradle to v5.3.0 (#2947) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index f2d748d25..ae6cc0d17 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -22,7 +22,7 @@ val properties = Properties().also { props -> dependencies { implementation(gradleApi()) - implementation("org.ajoberstar.grgit:grgit-gradle:5.2.2") + implementation("org.ajoberstar.grgit:grgit-gradle:5.3.0") implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.3") implementation("io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin:1.7.3") constraints { From 91bdd15c18218240c07a33a2c6dcc041a82c2947 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 00:46:11 +0000 Subject: [PATCH 59/59] Update dependency paperweight-userdev to v1.21.1-R0.1-20241012.212042-119 (#2946) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts index 32e298776..4face9389 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts +++ b/worldedit-bukkit/adapters/adapter-1_21/build.gradle.kts @@ -12,6 +12,6 @@ repositories { dependencies { // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.21.1-R0.1-SNAPSHOT/ - the().paperDevBundle("1.21.1-R0.1-20241003.152200-116") + the().paperDevBundle("1.21.1-R0.1-20241012.212042-119") compileOnly(libs.paperlib) }