From be8908e2b25bed2c1237335ada003b414e2a6c16 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Wed, 27 Nov 2024 07:54:37 -0800 Subject: [PATCH] Update to 1.21.3 --- .github/workflows/build.yml | 10 +- build.gradle.kts | 2 +- gradle.properties | 6 +- gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 5 +- gradlew.bat | 2 + patches/api/0001-Force-disable-timings.patch | 42 +- patches/api/0002-Region-scheduler-API.patch | 2 +- ...king-ownership-of-region-by-position.patch | 46 - patches/server/0001-Build-changes.patch | 14 +- patches/server/0003-Threaded-Regions.patch | 4044 +++++++++-------- patches/server/0004-Max-pending-logins.patch | 4 +- ...nk-system-throughput-counters-to-tps.patch | 12 +- ...-getHandle-and-overrides-perform-thr.patch | 199 +- ...edOperationException-for-broken-APIs.patch | 8 +- ...dates-in-non-loaded-or-non-owned-chu.patch | 67 +- ...-world-tile-entities-on-worldgen-thr.patch | 4 +- ...access-when-waking-players-up-during.patch | 8 +- .../0015-Fix-off-region-raid-heroes.patch | 4 +- ...ition-to-player-position-on-player-d.patch | 34 +- patches/server/0017-Region-profiler.patch | 504 +- .../server/0018-Disable-spark-profiler.patch | 6 +- update.txt | 0 24 files changed, 2725 insertions(+), 2300 deletions(-) delete mode 100644 patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch delete mode 100644 update.txt diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7a596c8..740d9dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,16 +12,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Git Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@v1 + uses: gradle/actions/wrapper-validation@v4 - name: Setup Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/actions/setup-gradle@v4 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Configure Git User Details run: git config --global user.email "actions@github.com" && git config --global user.name "Github Actions" - name: Apply Patches diff --git a/build.gradle.kts b/build.gradle.kts index aa1f6dc..ca0b451 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,7 @@ import io.papermc.paperweight.tasks.RebuildGitPatches plugins { java `maven-publish` - id("io.papermc.paperweight.patcher") version "1.7.3" + id("io.papermc.paperweight.patcher") version "1.7.5" } val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/" diff --git a/gradle.properties b/gradle.properties index 0e506ef..e5ce423 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ group=dev.folia -version=1.21.1-R0.1-SNAPSHOT -mcVersion=1.21.1 +version=1.21.3-R0.1-SNAPSHOT +mcVersion=1.21.3 -paperRef=84281ceeefb9d294758a9a292ba6c01da40e8409 +paperRef=afb5b13056ebbcdd3ae834c039046ecad4fa89eb org.gradle.caching=true org.gradle.parallel=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 12612 zcmY+pRa6|n(lttO3GVLh?(Xh3xVuAe26uONcL=V5;I6?T_zdn2`Oi5I_gl9gx~lft zRjVKRp?B~8Wyrx5$mS3|py!Njy{0Wt4i%@s8v88pK z6fPNA45)|*9+*w5kcg$o)}2g}%JfXe6l9ig4T8ia3Hlw#3f^fAKW63%<~GZJd-0YA z9YjleCs~#Y?V+`#nr+49hhsr$K$k!lg}AZDw@>2j=f7t~5IW6#K|lAX7|^N}lJ)I!km`nrwx> z))1Es16__aXGVzQM0EC8xH+O!nqTFBg9Ci{NwRK*CP<6s`Gq(~#lqb(zOlh6ZDBK* zr$|NDj^s6VanrKa+QC;5>twePaexqRI%RO~OY075y?NN90I|f^(P# zF=b>fZ73b5JzD`#GC3lTQ_B3lMeBWgQUGYnFw*HQC}^z{$6G4j(n4y-pRxPT(d2Wgb%vCH(?+t&Pj z)QM`zc`U`+<~D+9E{4Uj2kc#*6eZMU$4Oj6QMfA^K!rbl`iBix=2sPrs7j@aqIrE zTaZJ2M09>rp$mgyUZ!r2$UK{+DGqgl`n;*qFF~M(r#eh`T{MO?2&j?xgr8FU$u3-` zhRDc_I23LL4)K&xg$^&l-W=!Jp-P(_Ie07q>Je;QLxi8LaEc%;WIacJD_T69egF?7 z;I_Sg_!+qrur8$Hq4grigaiVF>U7uWJ@Hkd&%kmFnQN-P^fq0gB1|uRt!U#X;DnlV zo?yHWTw7g5B;#xxY`adhi4yZn@f(7-Xa(J6S=#d@&rlFw!qfvholE>MEb|VWn^g}G zMSrK&zQ^vDId&ojL!{%{o7?s{7;{+u%L{|tar(gp?Uxq3p?xAysB>0E$eG#$tvkk9 z2Q2gEP17{U6@UD*v({5MP-CTZfvWMItVjb4c;i~WLq&{?Q1(koX&vt7+$z}10{^Id z{KDjGi0JpD7@;~odF__0m|p;5rIrHidOP9^mwKe#-&JX-X@acc)06G{LO1Wu)#gvZ za~y9(fhA%UwkDOVU1LBJ`0ROE z4&)dJKK%mG@+CIm?+wt9f~@xIMr8}UH*K1j| z0pppo{7gv3v{URwxVMeg>Ps!L5IKxm zjac2egjgb0vH5i75$s|sY_RYec#>faqJk|AGgV;v=^%BM(^p{p;(^SVt-88G9f!q; z>p}9E4^f0=01S2pQBE4}9YqE%TV)*hlU^8k9{&=K76+*Ax^r=AkBb%OCP^P2nm0Ri z;D-|Zk?gGeU<12ti2CnPVNA(Pb)02+r|&yTWW-OJO7 zNLb0pps6aN?A~NJp5kj{{IOlf!5KWMleV@-hYLift)D>-7K+tgs=7Ake}oBnIy-y1 z(Hn@Hjw=_(x>dO5ysQsrnE%A*bk0K<-j{1Yqz@#n#jOL^AzCr#wR|WYzqk6i7v)Lf zkXdKxzuu20aP{Tbg$(+9&oh7cd(Uoqqf<#ujb$q4sZ~gxFbQfS zS)kNklyL*{2AELgjZ(LBu*>S(oH5AaJ;YiB@;l@=O%F6B?oanzoYRM^fQ9-<~^=3$H0g^JPMLQo@SZ@QuNvy)tyJ)LSj`+()#fy?{aV4Yg^7dlQ7AQM^3GLCR2dAFR zJjtfKiVqF`l-H_fz0HD|9g>)pOxn}k!vdZ=DO!7Sikm{Z%P6BrRkBS6W?ZB5W&7rT z@uYpf@M@a!z7H&o@-yrcCL^Ff3e7p3T`R9p?@o-acXmbTSa0>ZANzCSgovsd%;i$| zVus`not!oL#(W`L-!9w0jdaECaG4hk{V7IOs676ZquZH~0TX5hDq|)x z6T497l|E?f4)LA>j=S8}b$0LS=I4h|hUFJYJODT8Li@#6kF$k0)@*l{RnM1HQ%?VT ze-Pqlc!~t(oumVC*?5fwR;P6u{tHaZ~*LlD;B)4f? z?lpWfa2P@)g57flVl83Ej%P`2)gGyaPjhvD(%i~{`2b>#3!+y&` z!2nuwHMFA-zUY}f1^0B8<`N)Gr=A4TS@b1qykmd0Pq{?r)+1^^+D(=xasb^Tf!oK9 zBLL+*p6M_#ufgLzgq1zcSwZsZnQWFLC3`Yxdg-2=*tT`J9nrfYt)RF)YryBf8_gW{ zvKbB+oZLehfT)S#<|y1)E0hW^?+AnqPXq9Hu;v3dsMGdr{SVyF63;K<8VcgI#~}1i zLYSBL0K;RTT(;>2x=*!1Di9w0mwr;`CN}kM65|Ay{~z}_^JKOsRaN<~#9O^iiW<5P zYN7r~HV!#Nz~IZU`P>1Xe%4f~K}KcF#X&5kO*G}-)74S*tQ8CietdPcA1Yl;S=Mr# z`#MYY!{s^uo=jn7;k6O%(}fN+*0cWMpt~#n9DR<3NyU?+3D^AgI}S)Cu-Tljg`VY} zX1=fq$?8$DtOeGxE6f8lbS_6Q3C4+LDTO$}_IpM$Xv<|QSC%+Oll^q$y`7o@jD{dp zNDl|&X)r7wETa-#h*d`KXntxI(Y{vLha{$0i7@G8xx^m=c<{lJ9?p-i!^W{%j7-oo z0W^SzZ^(Wkyz*We{lEn%Yhu-ycUOHtrRiVJL4~&S91*D0MrLu}Q>v-Mc?GcWfpyz% zX|UvcN@krFO#@v|CtYM}g|=L3%aMo$E5<@CM%c*;?u>LOTz00@+dt1{yg1y=$h+{|D17U}$*^fE^H&8b431EUE z<9tv0V_#%#&1N#j7AKCj!tTK@J%oFW*ESW<(#Gl#Xs%v<@AitI?s92nLzm<)w3Wkkom1f$gcdUi%g_*jofy&}N#luL<$GVIe{iQkQ)sIHVy zBgItnPBFamrv6Kb{eE($Q(f`ZPeW!Hm%Y@F*OF1sKB{Yy|C>WEv_mfvv-N-jh)B-5 z4a!1WcT@9a+hGaBrc~sz=>G?Q!*Zp^JFRUvBMyNR1;`)j$RhH$6gEyVKhd$&K-CFT zXaWC-Y=fyOnqT84iMn9o5oLEOI(_3fk!W^8-74|q1QhQ|CmT0i=b;6Z3u?E{p7V{? z;f#Q-33!L+4&QQcZ~GAqu$NS{M;u%`+#9=7^Oa5PKvCCCWNG_~l(CidS!+xr-*gg{ z$UQ`_1tLT_9jB=Hckkwu>G{s0b0F4bnR7GibmHo?>TR&<3?D;5Fb#gd8*wYa$$~ar z7epl1qM)L{kwiNjQk}?)CFpNTd?0wAOUZ|gC{Ub|c-7h~+Rm(JbdoRe!RNVBQi!M8 z+~U6E2X&KSA*T6KJvsqwqZl#1&==Dm(#b^&VAKQ>7ygv*Fyr;)q9*^F@dCTg2g!w~ z%hg)UXAUyIpIbLXJv1nZX+a_C)BOH2hUim|>=JHCRf(!dtTidb&*~I!JrfRe+PO>w z@ox$G2a3i9d_N9J=|2$y2m-P&#PTNwe!oLBZFs;z|F5kXvBDn<)WwE0E3$ow=zg3R zK(9;sf0t;VEV3@gAg7jRtnj%-6O@!Hvg*;XcUAw}!=2*aErvB(eQIm(-UGmq^J=XN zTqJo$Y|WKo^HlBF3BXJrA#}7ZLg=r*w`I*~Ix`o&2k8^(0mt8Rp=A>F`&gehhp@Jy z^e^#B2!~$LvNCKugg)8)-G%&THdk~kfextilegP9?#C#()F59U$&eo(h|5>ceo*Em z{PEE79T$YP|Kr7K`WBHbtQwyxFkCl6xX&+oUf90B5xoi3_5KHHCyEE*oPbOQkfMz& z6^hT8_NXd2iWk{q9IKae1{_7hMPH8I7_BMtVOM4 z6jm?E0QJOn$qrgsJ`9w##GB9?G})-GXSQo6(tYS(Q0-Ct$co?Zzl0?NHsDRron?;_ zZZgQg)%XW>P?8_&zoGuF(>Och2kEJXsu1_X&~w87x!b z>~h!a>e7{`p@+#hXF88wI*JeWRZ;J4ev4<}HWf|Z;(7$E!S5l9wzBHFe>^I{2`a;a)QnAwa2xv1e(bq$<}!8o^ofGvYpk7dBR+`*%iE;hUY5 zaHF}OjGO9r*{%lmcK^uFiTHgoUD`^9Nx@~;Bg!V* zuuJ&ti{DQiq7RyJAR94wem{}cPK1J(Yxnn_{=>?USqz-~&QXRStS^s-7TksZ$AEI! z#og36s3JGtGU{CnDHRFtipFqvrE*gw7_K@NN0h+ItTq@4fqN!HeQU1y7*X?9+IfZT4Vxebpt z%#VzgdDK~-&+=Z*#>=n#XUhNvBZp3=Cr41jMqwJkHLf3L7Vm~V#GgJ(Jpii~PmJ#s zA7Ft!{xD@z>9DUb4JbiUBdNEcU4BO$651iN*mp*f)HbRRM`Cx5cR?5IfEcU{IZWwf zz(M6CDv)>xa3x}K6%tP^i15P1&&DOLK=k~+jNR$UK3frSl+|PjSC-dBItvD~LL! z>_g(YYdO4k(5EbPOw+v+;G7~jYm>F@Ai|o`gs%F)F8tDz$dl7Q%aCe|v|$UkAul_R zNlA-beBX^IJU?kgS`E$it7nF4DaI!SJAGq)2P&Few(-|tp z?K+%D3e4{pfkayrcbm0ftu6Ol2ZzdKM+4i!hNP3NRL`EvvZJ3yvNr2MV%igZ4kj``Qrdb_OI$7jWP z;l0DYf&0(-*QcP5zrP`HVznW+SbH63Qx$7_9~NjRNg7eKqI!UJ=XH`g^=t8GiFTu( z?2L{JKEu%jJx&XjNzU(*!ZNmL1@RlJA0G$2_LrAb_7lmjil(GSlSM zwTes`m+3R;3#N~Xg#9owh3ycXV8@ZlaY_16kpPFA={721b~URO4HD3sp%fmkZM}k) zZB0#)kP=RkNB~R-MCk8aljG_bagt4vIb~8)BV%(b8_;)&Kf9GX+%O_cNG|(D$!3&D zL(I8}*LqN5NntipFlN13=`D>6!{D@CFMBH0kW3=HccJV+xW~|$qeFR5i-2{X+iWMu zI2$gepQ)H_B%ip_BlWOQ*|pErXs|4ir{IHccgaIJ84irE{?+$KDABXr&f`jB^V-c% z$$u`uU1YB^{<+UN2cNg#7&0bz@yF?5>j|;)5&IV3wIQp58X#OE-M^$HdyvL|Um5t? zhZlAG!Mz%XkUe3t471JM*Yur}o30vzu6RN7gJyNcf!IItsDO730mcJ*O!~V``y5=3 zNJGp34DZ}wd1H6V`Uuy%es>BiO_aE-S8jzir#$& zyk)@2a5tP$@g%jW^b^JGdo)X@Q%sE`^lDQmY9m%uDFpPX`w9%=yQ+nneMm#OaXcD` z9}{tn5A2b2z9783vL2_jSao?uxJhWJoq%47*RafM4o0@gY(p)F>qT4^XM5GLzV#6j zC+HoGhAne7o_w{WUo(B++z7lU3Y0k1rYv9|TSv0vR-Du(5=VakbbelgZTeDn+a_Wv zq_j-^+Qz1WAl;Zg>ahX|CERbX1V%B!hTKN?M}fGoA07M(WU&NfT&TmN`P@56U2 z^)vLDs|Ln~0iTtn-?KTeQl@T&bskJFuTUS!m+$CS9vnd}8(UMO|Kv6TCfGN9NUu&4 zL{)GTxPq>fwsJ~aU=4Qhuq8*RzDsP(LZh$BHezq&9gK$IS<|DYbm})$QTGCS6T;Dr zEkLct!b+#<1r9OKG@P!f1wm8>=Nz!7OzJm!g<+`?N3;YaA3(P@EL=(sTaRMDD!c8=-XN^4BXp(eVkj$NmEMYPP>YJ4bJ3yUud z<3BeJAJ$6z^TuywnfH5lv#$lgwraNw{IV=tIznPH1DT`v-5yS=!)J<}xxl}uZf9azA2A97Haf!;<3y01hlw?dWNEv@TLi1s-mO4vmIT%O_42nS z$VRWrs9NngqRRkWAnWkn%`Rw@?wH|)7XL`EL5EZu$qyJW31&CB^T_)qwIv!{;E_6 zo-9XAryQRlk-O0>o#-SZO>|6OYq;}<*>Wu1AsVRiXY4f8qb;+sItv3AyS!4Ry+q}) zA!pAB|BmC;=RIOk^^vlsEH(!Q!7_1FK~ZB2err*o!+b(r=m1b?$6d!%zmN+69LXnT z&gRmM+n_R-F@sT*IYv0_mGPvur!u`iWbQO7SqiGFLeY&yga zf`lM&B74FA2C?N@8_z652fjhBEoDUKbP8hL{0{HAF%qDo7)o3=3rg#6)T7%%5^wl% z9R0*S*<~>nzYOdQk2l`9h#t+gJy_xujw6xjV(8S<_DbVg61&pT%Hi42l%D73G?adn znB%UdNM0p}lEF-P2%TAMam2zpQev71e>a$$%i+r~b+D9G9pF|oY_*(-u*89oKsXLY+UIbqq)MQ%(GYS{(*n_S_*RN$*~`zUtab%0aKwhx znc)Yo?{xq1sJCgQD)TeTci1ucvbez9q=A72H(-SB18Kl&6^vHV8^i!p@>iF!DIw17 z+8Q)TNisB7>pwyww4y)yJx*wX6SJO78eLBC-ar1+k$Z9fy;wBD|3kzI{<+l*>PSY^ z_?nLOZaeWbU@C3hfK?X;Di*8CHCPkx2qco6(ZyJdqSzp^TJ_5Lpa0UP{Gy+!b0Lr% z@xYxSjUKoY6L#>$qx~KD$-0=|OF7zhVP~ntMgEALYPIfhj@+ z!;JJ7te>CcovruwHsJH6Lta$nm|%^C@=V-rmhU{+I~0(|XHQ9jt@L7pb{gx#{4r!) zg($FyFTslcgu(~6lYr$nW?)%*l#VJ=R-jxK(x=t1bWlu(nL66T#qj%3aZ@uVhy}Co zDU_q61DD5FqqJ*#c|(M5tV)XBN?Ac^12*q)VN4yKPJ|#==S_`_QD9|0ls!`2)SwuHDRA_OfXQDq3%qW&MZB}Z!=k-9xqev8jHz(H z{^D@cIB~QiK>~wa)A&^Ll^Wi6QgCzU;iv-BHsLBs zH7=jN%|>0S`SjP%M&AF1PNVDp_FZ?2Bm@7`DC&v(pYrw!!yD#4 z6+<=HS0Ln6MhoKxF<%~H`y20{vf#pxh=;j{zY381gvAFekgG|>G1zo8$&az{V=;JR zy_puF4$L$?EMhT?;TpQoR*j16ll`#AS4e96C}yp_aGKkBe?1H|k_;gG-~Xorc<;lI zkB}fB{$c-D2mGA&{rm<*@F5)c3X+6??g~XoEwuzSuch0D@W~P5(2I8v8F$c2$Vw51 zP#YLSBDqtWW^EYBl^QYHF+MA7am6f4DOhwnJM=W9$uvMOsZ%_~?)2C#wb?CkI$7{K zEi)=#|5pFvg^){zK5kpBLjB2kZ+$ZB|L=W|aNwyyb(gC2l7bcpx{E-H@)q6@D6N^xh`{1E%ItF2$eeB_SjI@b2WgTpS1thwg&n`jiIzw^TtXUyB{00($GIq>vbj|}bav}}Q_~wp3>k8!E@hVC;OMUTu|= zAy#vXH*GrUHu7^cNZWe1>y;2(51js9wbu+R3Aa*(wzH9+X0dIsf&gc_x|_LP z>~CF^?(~U}+l~ehe|i>?4eo!xkq&Lk+RR-1duNP#o~>@1x)s&i&u zRaYL@+D&_M|JLI6fHbEr_`U;HgPTh#E3?sB)A$*gqyBgg*ql|a-m*TX5rACbWKCE6 zdeQ`v8m6>g^ugv`p|HY^#1QZrGGUj0^HVDc@{?Q0yhalbBEV{+|HzC^-{&e{5K%z9 z6Bxtnfu1!@Mp+Q&*&~;FOg&*Vm<@4b;{FG0-!UUXX!|)1w}op!B_|7_s~d(+=9Gba zKp8`LaB4D(H=cGcspJ_TjYaOwMb=sGn^gtUVhK!UI~2KKYEE-NC}F>+BEY7IVvy%KRvm00tg!Q`y=er}wpEetX}K@;}(}{s9AzV#q2@ zBy7}->|N?13POrs`;U?(qAG(I$~Gt+Rgw%aNZ_0fs_utVvRJT-7z4!@x36v@=NBX=IqkK{#Kg0w48de@?#Yb4M(Svj5=T+<ONr8-oh7l?Cji@+erqur zFhZ=9|Lk=$`c}v4u`)-!!UI=!9Jo@h&7p4RlS#u! zZ7-prn75JkV?VjptX;@$#`U`{vB!=Z?V`T*FBF>J?vsML7e6@2GbUteMFfX-TUu{2 zLNIG*;dV)8GV8gAgEf#)X3A>p3^CRka1v?~8x^anBhQ=L=LsOl=&pcOYHo98m##ye z34MtGCDK!`ptl?taGMr5q{!zVc? zG00e){TV?`YA9eB;(lA3lXI?RrB4BYQGk?vOmTIUJED=(`_*gtn2DB-t4WW54as*W zb2kD-lWX>lb$+W!VFakki>B^Vc+u$?NLF>)!U%b@Y}gYJ>m2H=^x0=nsE0TF^Yu0h ztgH8-o1%+jCk(+&`|)tTfEVHq0cMeFa{Uz)X$;fCq%Y=SOWML6bYfeP8j5hktL`KK z(18`XrUn&WN9PtFxh&dX`y~YBsmdhi7Kw%tKzM%^VEhdD<_XkulW-x=JN6OPbFI4@ zzDDRN+f=@{0h*MswwOqG6gJ?{NuHx(y-|FUGsxyZ*x0~$MW(eY>vqq4Fh#t7uzw=- zKB?|!0N~!h^AMdLa)oR!Ca#HZ9&Zf)ghuO<^RN)4twRlygHnQG(BE{cDc5E}OF4;xss6gYyV~EcJvJkX)xNWb=@yw!uq0v-sf^rvkp-;?DPWK@*SEw|V;IH=7 zfQqEV_>DjOPT~8X*J|H8=&RnzK4~S7ML~nLX^%s-Vqc^aWy7N$y57qciZGcqy#=zU zs8hcHiI=D$+RB{|62{ohCTiaML6FI4Uhzo5D{Jik@poCs0w7F)*w}F4r0sJ~#u-72 z5bK=ANt=M$Dh5NKnxGsg9NRR?WD-x|FhTwBjd zD<-K>44DB~i%frJOfnzh1R>PRY34kw!6~p3M$JLaD1r@`=h)~Ngks-(gdXh^Q?BTP zZ^Zj5w1AwtuR2$~E7s9iZdF}z%pv1em^V2rM{1tLUY@-+Sc0(9jA|iZWml1;v13=U zHf?y@#mb--7z6$ue>`qjhE~brk$AY-RG90~5wcBbDReXR2)pKg{L>;H(DI`U!MLNQ zY9rFJP@ZQ}jlcMh%WSCo%vf+nd0Gmd*F%KMIe>slCUh)8Ma|;M_I+v#;|ueg9oLg; zq2HtZX%&#F7vdpNlkX?}(C7dGC^y#NB#m4%69RzTNrk%4ol~hSI%>2r6B|*ZkW(*P z;u#s;+faHo{tfy+1L^RzWDi*^JR0iY(zJDB36y_QJ+|E-2x+cY z!V8uLNktH~q>WQZuY!Ap66WP|E!0PA1jK~)^8oJVGbspJs6QL!!-5Qm7 zHYI|_`Actg?vDzdg5{86w@GS$G6ANzff7->6i5pB$T4O}`fZ_;{217Om0gN5zTr12 z5mW{hCzCE-QubjxN$TAE-XgI-8dTY@OZmq`y+y_>dk*(qXF0{nam|q@~i}Utp*k{yurq(DW54hkDT4bbg z=_etM?Nf5W^o-HEu9_?&xEqPg^P^mTxLH8n%u$!mWvFG|{&)jtnU&6|5-`~eaNz0%D1BDo`{ zS1N5(KW5v^2eLdd_%`uaRndF@h0Uo6=M|8?b~KbOLZk{HXEnGmtgZXf2inI*1r%n! zQ3&%RI4r{f&dwW~HwH0Ked9b!k6{>_19H z_Ai>5IChDMY(FfMyG%;30?SQ{iV9KyGru62+Y)~qSQ91}b~}w<&*}R&1c#$O`H@~c z5)2S_eXx}M#N{MuGeQS9@#UJB@;W_j50b}jIhxMPloEFQZdvwxiU^RYycTzgK)-vl3LT&$L8~@68$C8~5_U{cR$E#w*x65(qw&eoL@>%ZHvj zWnEMlSh*(o&oy|J7eJ5OD`ssy%F?*Vp?`Cq;FShyl{ZoKCG5g{y}>usznni#8ki(i zO{w@n{iAj1_ooX@+s*!uW60WcH~*bNOT6z%0jVML5};wVrQp~`Uss_{cO2oud_nNA8^B$?07fJ6?iI)Q zuo9G)O-z)DqstrBqf>B%S05hf-wep0@$BFHKSrkZ{za3D)yVzRz)2{wf8(Wp+xyAM z$rtyx$gi3A=V~V!`Q3;BM0$>*VVtxEM|xDL^gew7ydy3Q6YzD&THRz*q33Ms_D;M- zbCx1Ft#UNB)V3bf`~{ImI72OTp^|bF8?G8#FRj+Biy8ET5#rA3sd|0FR@U(LAJ%w8 zS1%n8Z=Amhw)92rIsof=YVWF4jw&F*j1LG@-`+cR0-~2LqXRH8(Ccne{y#MCPncF64U`0uO zWmi$dlii~1D0rLR{qc|_2M!C$t8^=G7xQY)9!#Y331A|>N)EhmyVdLWL9I3YLJ`7? zZmpqUJB>Ni9oiL)^1IK1UoMyhWE{$9M2M6Xi zPKk7GpMsA6vjZbU7~i+u|J6Nk|Ci!Y3UMUT2|`M;JsNQACdJ%ooo9Yt{?A+0hMpxi znEa~~sxC>rKrU6bd=WRb;%wsH>A#j4{({&1GYSNR57Gama(3)2A;SM>qop}l>Jk2* zn1+C$fIxuwzg3mCU#SOqb-wOCb6mBcYlA5+mt<&_J~sBxc(GQtBFINUO~Mr7<-uu($>P HJ4oML2Lo<@i8BwbL^1~GkG`E7C$SEa_ zF^}Ea+#Je`Xy6;#D0FPnSrR%Y!QGA~NA^{oWmW8C<3dr{x6wWQ{4+bzemqV5W$i5~ z=J0jXZ>uZb>DT@0Ks?4QJ{`z?8JWl3$y;2pj#$XP*pv$>$g(z43{YH9KmmR6<#sIn zA`#=0#sgycaBQ^&}Xba!|KaZ8~b30v~nLt z9%#gz_*=~KD{3t^X~l>480*}PhKN=??g`RV|4Ud{Gyyl187MJ}r(#e+H$GEdI+p1s zq_25h;fV)$EPK%Dw-(G=f`yHB-_tttsC!?k7*#!|4a>`Ahj8nm?&n>NRs%jkZW^3-0P_yMP5&*6a26{MRj1&TPF zyE#|c)5uUHzMWx=rMKpuPih*V=S;W3MzIZTw2uTbr}8`p2bm+Z6Sa%vvWAWSf4H)p(+ zSQ8;EvUa#wqWV+9vmIio(%7wukK2SwjUS8Yl%Rq%=~PU)2$Tvm6`1!r3H@U#_|bB0 zmlT1PS3wPB(b&^+@YY7Y$n4l3mV3-X0$>z|gZp6O*Lhzn&?Gad2ZCF;+#95-Y?#y+ z?*l@Yf=a4w{Px=o!N|3~_XKfk&G;fN>Ps&dp2FpA~qD=0~=!NOS@B#XAKKkND>Y{4>rqxrViKD7;?>j8`R` z&G)3FN|dfsxnaI^!d1G%=>AbTTxZWo;n-DLrQ!sj=f~VAOe5zhGS(dgx|!ls62fbX zV@<7Ck^!}R=`Swr?(7w1rY6Nmq~sfXJ?TiKJLn=&SQdEt9$@0 zA+h1Wbwbri0s-stc8yVq;mRa6@kEf8^KXUz&jcic!+avDvvJFa>k0ioWug=T3oPw; zyj4it&0@>_*uI@2=^+T7sL1_!^aJW@Xfo8aC#3^WtQC7fET8b9C} z*u^ue6Ojn z7@(eskJ2+cNnH9~VyfIh<-|7!je~vGy*odz(sk-u$~SrYF3glruZ*W`{sqnS+9=;Z zh{D@MSG91%lr&ua8%$sJF%y1I<|e;EdfJykY8#D$Hc_81n5`$7;1N|b0tvvPLzSg& zn7!5x?T*@rQUKcUhTIjV(rw*5oQYlm5DbEO?60#mohHfbR$3_x#+PZoYi@Vd4`#YgKyTd^!4n{fN~WZDY61sAOm6 zl!d^i*a01QxpWM9Pcl?&{RgO}uq%ErOk5WpECvnfEh!*YP&1Sl)uTN4hg??Vqs~i5 zYsfufz3?{TtwuBN=`0~Qg1PlWH#OGG$ zLLWU17$v``)CE1cds_7kj8mJ{-+l8{DS|zAQ&3|qpOY=!J|kXUhXue9|H>4gqk|n) z-i34GmxLFj8asb3D#D&=ya*a5`C<=o?G;Ev^LV%;l#nH#O=7Nh@z1Do>j6Q;I5S2P zhg|AZbC&|c7}uSJt57s2IK#rSWuararn-02dkptTjo*R{c5o(bWV}_k3BBnKcE|6l zrHl&ezUyw^DmaMdDFVn<8ZY=7_{u{uW&*F<7Al6};lD(u;SB=RpIwI)PTyL=e25h* zGi{lRT}snjbMK~IUx|EGonH+w;iC2Ws)x>=5_{5$m?K z5(*1jMn%u0V1Y%m@`YS3kskt~`1p(rA4uk;Cs!w^KL$w>MH)+cP6|XKr4FfHIATJH z!EGAK4N>1yFR`-zW|w%ByRe#=&kA&#WyUldDGpt!wf-8SFWiSi!5QZL+l7*CE?u!NW1T$<1rdLJ9y3u{_zvHaM?#Rm4 zFk}^1!ffcrB|XK3gsO-s=wr*sUe&^$yN|KxrA)uW00Gu60%pw_+DcUjW`oW<35OC8 zq2{j8SgC}W$?10pvFU83(SL$%C?Kctu3*cs0aa%q!fjn1%xD*Jrm!F3HGR9-C{b?- zHp(cL;ezXMpL@0-1v0DMWddSDNZ5h?q50cOZyVi#bU3&PWE=(hpVn|M4_KYG5h9LffKNRsfhr^=SYiKg?#r&HNMi2@cd4aYL9lw(5_IvQJ zcB*DD()hUSAD^PdA0y|QrVnqwgI@pUXZXjHq3lG2OU&7sPOxxU$Y3&ytj6Qb=2#cC z;{d-{k|xI*bu+Vy&N+}{i(+1me!M;nshY_*&ZQLTGG*xNw#{RpI`3^eGfHck+*38NRgiGahkFethtVY=czJs#)VVc{T65rhU#3Vf?X)8f0)X{w!J3J{z|Sq|%?)nA+zo?$>L9@o`Kc|*7sJo4UjIqu0Ir~S5k^vEH};6K?-dZ0h*m%-1L zf!VC%YbM1~sZOG5zu&Sh>R;(md*_)kGHP)<;OA44W?y53PI%{&@MEN}9TOiqu+1a3AGetBr$c)Ao3OX>iGxmA;^^_alwS818r4Pn&uYe^;z6dh z)68T|AN=hjNdGpF7n>y+RTAZc9&opTXf zqWfK_dUv=mW{p_vN>|(cIkd(+Jy}qnK{IW%X*3!l`^H~FbAHwof+vLZ0C2ZXN1$v7 zgN&R9c8IO`fkR{6U%ERq8FN<1DQYbAN0-pH7EfcA{A&nhT!Be>jj>J!bNRw4NF|}! z1c70_#fkk!VQ!q1h2ff@`yDyrI1`np>*e#D4-Z~*!T^8#o*$V~!8bWQaie?P@KGBb z8rXc!YDL!$3ZgZZ%;-%~0Kn<+d+{xJ$stQbtN8GWV?MCJvzPU|(E(1z;rFw{&6vy) z3*@y%7Tx8rH-p$boS>bLyod?OKRE8v`QSBvGfY6f}_{Zo1q85xoyOF16n~yHx2W ziydUoYLkJmzq|n&2S(O!ZmLdP1(o1Jsq88cX)x3V-BK5eF&0e_0G!5?U7&3KN0`mc zH&Lt)q8!d_VgzxyL^(@xrbp2y)Hmr^V48));RSfE=*Ly0uh9!$3dv-vMZr2URf@l5zdwLjGZB zugY>7_fd_vbV*Qv1?H~>Z%RD%nEeFSI$n$$Lrpc6g>i4+XdBB!%zM$Bhrz5Swzyg? z$~I~n@~-wTBY3-T&pr+|gC+OHDoR?I(eLWa{Z#Rsh>lc~%u0!&R|s0pA*w<7QZ}{i z*AFr~0F3y~f$MGh_HDL7J_1?SxKL}fWIk!$G}`^{)xh*dZ5kK>xGL9>V`WZZg_ z)^Vm)EQK`yfh5KiR(vb&aHvhich z_5o+{d~0+4BEBqYJXyXBIEb1UgVDs;a!N2$9WA>CbfrWryqT25)S4E4)QXBd*3jN} z?phkAt`1rKW?xoLzEm!*IfkH|P>BtECVr0l8-IGk_`UjE#IWkUGqvyS+dMrCnFl<7RCgSMX^qn|Ld_4iYRldO zY&cHhv)GDo8nKvKwAbfyLR%t?9gG?R7~PSD#4D-;?F&!kV59O}neYut5AGbKwy-(U zqyBi=&Mgj|VIo>$u!DHM`R7O?W8-idbePuxiJMH``6c_5L-chKd}=rGC5Gfrc{f!* zWFEBm?l@_b7kzY7%1RQQbG5V<4=ZlkZ%sF74Q|mKOc7Ak7dP2#quiGcZ0_J%7Q?j{ zv9{WFw;n5G-Mn%r#0R;{jLt{yy}9J6rQ(>X9pJ`7Xy?Zv z=lNit#qXaq?CnElK^zF~sG}U5oCpR0T>FH=ZX}Prju$);?;VOhFH8L3I><9P_A|C+ z{;>~dk%9rrq(snjsEm}oUz2FQ21MCG*e?g)?{!&|eg7PX@I+Q0!hL6C7ZVY|g2E>i zr!Ri2@OfEu$)d52+>+cpgh6Z;cLYCZ&EMR0i<^~4&wEu_bdo;y^6}+U2GIQgW$|Od z_jg{O=pU>0-H$P-EOlWyQy#W0r@@_uT}Lg+!d5NxMii7aT1=|qm6BRaWOf{Pws54v zTu=}LR!V(JzI07>QR;;px0+zq=(s+XH-0~rVbmGp8<)7G+Jf)UYs<$Dd>-K+4}CsD zS}KYLmkbRvjwBO3PB%2@j(vOpm)!JABH_E7X^f#V-bzifSaKtE)|QrczC1$sC<<*Y z$hY*3E10fYk`2W09gM_U<2>+r^+ro$Bqh-O7uSa)cfPE_<#^O) zF+5V;-8LaCLKdIh3UB@idQZL`0Vx8`OE#6*1<;8(zi&E7MWB1S%~HAm%axyIHN2vd zA(pJGm_PraB0Aat3~?obWBs?iSc*NhM!{-l_WNCx4@F7I?)5&oI|z{o@JKd1HZ}zf*#}JjK3$ z-;3V*WJZvUcKvSOBH4c7C{fl8oRw8-vfgKQjNiR|KhQ%k6hWNEke(k8w-Ro| z7Y3)FsY-?7%;VT64vRM)l0%&HI~BXkSAOV#F3Bf#|3QLZM%6C{paqLTb3MU-_)`{R zRdfVQ)uX90VCa3ja$8m;cdtxQ*(tNjIfVb%#TCJWeH?o4RY#LWpyZBJHR| z6G-!4W5O^Z8U}e5GfZ!_M{B``ve{r0Z#CXV0x@~X#Pc;}{{ClY_uw^=wWurj0RKnoFzeY` z;gS!PCLCo*c}-hLc?C&wv&>P1hH75=p#;D3{Q8UZ0ctX!b)_@Ur=WCMEuz>pTs$@s z#7bIutL9Pm2FDb~d+H}uBI#pu6R}T{nzpz9U0XLb9lu@=9bTY&PEyFwhHHtXFX~6C zrcg|qqTk(|MIM%KQ<@j=DOjt|V)+8K26wE_CBNnZTg+Z+s}AU|jp6CFoIptG1{J*# z7Ne~l;ba*=bSwAMQ|Vq#fW~+je4PXA91YFzBubNF?ovIOw-$C-8=Ehed{lGD0}(Id zRe4sh8L>&T%{>8o))he}eE;5_ zxoXk3wX?MyNl-xF!q1d$G?=wp^`@09(jU&X zOqZIBI#dN`2PJNdATR3ivtub|nO$dulSaP|e4)WXF1YAGN1pDQIbIjXFG!oC85Mt; zW$eteoL{y^5t4TMRwP$jNPjZFpGsWnGe=jMMqKtcZm9Y9PFZLi*1p@qoKKub^T@2+ zk$@*KYdQ?Z`}<%4ALwk*Yc{(WTf@#u;as(fvE^9{Gk)lWbJP*SjttWofV0s?AB({~l zZI1hZVWFT~W-T?nfMMcnCS4-#6H-MU7H$KxD;yaM46K4Kc@~Q>xzB+QnD_I`b_l3m zo9pRx46b!p?a^&zCDwygqqV3epjs(s0NQI6ARA1n!Yy-qduipxQ& zUAlqRpNjBS+y-ZheD(!R;F}&^V_}b_gqH%tVZ5%%ziO7k^w=es+wZtK^i*vmrWNLMs{oWu_CIov|s1raZiS)>38>pYu;i+-t zI_DiNe6aA4KTZ2P09qPj(0~K4nUq^0+f(2$g`229zkG4jLzRvJUWE0oF1XHL4t3UN zDH466G56sy9hTZoAJB!C3;@F;ONxEk5u6Mv%zdo}Rq`=* zw1n7MOhfNSV48TS989ArIcj`C%Gk8~93~u>)!Yt2b4ZriKj9x2d`H2HQNJ=I>hkDlcZn zqRj>!;oRMTIOu zx|Zfsu~v76T{z7AC(jxj^c@tnJHZtGPsq$DE!8kqvkDx5W?KUJPL+!Ffpwfa+|5z5 zKPCiOPqZZrAG;2%OH0T$W|`C@C*!Z`@Wkop{CTjB&Tk`+{XPnt`ND`Haz;xV`H^RS zyXYtw@WlqTvToi;=mq1<-|IQ(gcOpU%)b#_46|IuWL#4$oYLbqwuk6=Q@xZaJSKVF zZcHs~ZBl;&lF3=+nK; zF`4gSCeZXlwmC_t4I`#PUNQ*)Uv&oGxMALip|sxv^lyVV73tKI7)+QY5=tEMas{vTD-BaTJ^*Y6gq~PU;F5X!sxqiq$iFCo+Uv7m%1w((=e}Vf*=dtds|6 zbX}91!G?C*KG03eHoN}RZS9DJxa&8YwNCT8?JxMXyZqZr13NA|GB{+vG`08C{V(yy zf*Lw$+tYSU_+dI`3n{bMrPdDb`A=Mkg!O=k>1|*3MC8j~- zXL79J4E=U^H=iBLTeHE_OKzE&dws8RNynsSJ!d;`zK?P92U{f)xvD7VQVosrXZrL+ z6lMVdD1YgL;%(1cq{#bS6yXmp|DS@nax#AqqlZhtUQdh<^2vr5`EpAO

LGYq)sa(w9^3-f}NHy=GR4v%t2YZly3m1G@5y`xBh_HGrD%f z>;|Ty?9FiJAc&UVD(StT4I` zfVQwxhE9bXE6r2mKO8Ag7{L^jCyqQb0QqKDPE=RAgqn8q1O^>(z7h5kE(6va%QqRZ zkIOmp(})rLSS(2{=C12e&@!W2=Jel-^_R``0xHO^+t!(oXbcv5yhD4g*$t_F)_5Dl zSVCgesW%;DtYPCFs{G;GX_o?1J3;QQPPv)rWw;>} zJ&KwnUqwNXloNXlK_+pNDfI~hON#SokVJb&ilg8d7^NWo2ZQymCqQMnjfi>ePibjr z-Z@q!?RGN$Mj}Nk){X_vaj6?Mj$>ACR*z|6MsXy3VZ^PFn@yHkPo(>m(iWepn8SC@ z>D2;R4m+gDRZ=SIX!b+CP(qE=JDIUkn=D$aUu+Ihn9-+k1LS3PreQg0N5eWIG@x${nC3v^7caS>1!PKNAY9J z#}E}Q9w#SP>(GY7Hbj&z4$Li6o5taBO|4+F`yS9zq*LJ<38wy4I>HA9(&GYrk4dLajKGww))BWli6Ln1A^Lda@N~p+snkb9C z@OthI+<##vp8!HVQT4Wk(=@zQ{OvZ$EKWS73+JHb)eYLGD-cqi6^|vd$<+IHuc?Nq zW7JertT~3))4?J|28n$I@nAD0c1%9C&IVhEZX~mUsf{efyS(XNG%ch;!N~d7S(Ri7 zb&=BuON95aVA&kLn6&MVU|x}xPMp7xwWxNU1wS+F6#y}1@^wQZB*(&ecT?RnQcI}Y z2*z!^!D?gDUhc@;M^OpLs4mq>C&p{}OWVv<)S9KMars@0JQ{c_ScGsFo3BJ)Irg++ zAWwypJdTO-_{Uh8m(Z!3KL7K{ZZzKHj;{M8I$mV>k znTM?sa0);^=X^cglL`uC+^J)M7nEa$w=VwFULg~%DJllw+7dJAj3{qnP5i3@wr7%y zjXp?Wl2%Th=my&3u?Q$RV6N5tzKMSPTsc#J+-cDDp~qFB6bL2C8AS7Y3PKtVhdhl) zIaLqH5+OnWPWSt(lQCgkN8lczc-V%_iZ{>#1%Z$N*>lu#S;0MZ$T2Y8Kg!U;hAZj> z6S#%$DQ_`Ic%Zr@?}GgjRXg@qTj^17n`65oJ@Wj0u1X8&+UVd|Xs?J+i_^GZ94m6= zUc96~Q`OJvlKB_Lr15*Yw_PUPEr?f?H&00b^-W%26mD)(n(rGGNfK9~2h=C>p-7BZ zFd&*&Msdu{w~(eyFOglwCPH^Rb}O(N7LtS+nnEwDx*pGD?|&9Si~M43a+*L(b0$5A zv`T`(G3xO;I_sx;FwTP21ZlfDpz zOo?}Vlgf~fo{YWm@n_JyD*frOg{XsvBA~|Tn4V6hu>Gd>89-rblfVJUaGvj6X%NZ} z$tFF9sx=4_$*c~G`9iPLGh@=sV+O{D2-t*K@J7H=`V+oVt}8?04WwU3h1BgS!f%1P zFak-T#7`TtLcR=Yz>g0R!ZQrH!YiZOQN=_V-UyncN1Rc18?KY?#O`v#JK+pq0K$~H z3D@v9DZF42R)b9#BBX{^$DOMlJ!g)Gc za{o-1e%F6NvgKq9tC8pV+9S$;9*zNv{J*)n&dmf~anP1)4~N%~h#c(=B#3*KgzhCKhFdgDoWi2IDog{RVyzK|Y`rCUs3T~pJMmdZJy4?b z&s5G=zhf**(t7Y^oC_mcTsE-{^}wiaoUu&?kojLKs>SJPxjcP>{a5CbXCx92AcBE) zHtqP}LjZ{W>PH?Tu(E0X=%{PBMW@F_?#7b&#!^q`<-5$ur+-q6 z{dn=(^UZw6*3-XM_(=@<1_*i&XM4=0t5u!gm6 z{UlmNGPKgO_;e;q9|#esq~Sq`<}%d{+sRmhvsA{5i*91=tub>OZZ%)xUA#4q$dDyy z1`w4%?OPLg3JeZb#cqSMO?*Xn%|-FCcuH2i2fn_{IFusub6;NQdN|7TD1N?%E8*g? z$apAt@cEe!I%jB=*q$p_3=t_5R0ph%{qaq+QDg!c99Y!Xa!&oDZOeis_ot)gNXr{l zdY$|So2Qed2Y7KMNBrS^E169kG%h<+z{Z_p_;shB!uY)>yAVcK=&!bg`lVg)4T1|7 z0}7FpfydVH4F87K@c!nEG+WGKm{Ouo)Slpl;#qcEIQ0zdMfLA#;dBxYw;p;KoVv6| z3_D5&7rJdG12CnDSvZUW?$UC6^UVSW^|vw|o-_4bz)(w5(3AiVhpeT(|=f#x_}E?s#qHZF#xA6AF_ujl$G z-jHD%q(d2}v2PhXx&6YWps~m(^+RXl91Q#xRRJBhjKl$FG4bk);|ag;ieUZ&!Ii3$ z(iGz1+0m7#g5>ASldBbNZL=ZHh=tmmJt$!71; zIML2GhEz1pg@1rQN(M^_691wAGkJ@Pga_05WuQ6! zG5RkGY2^`@(H~pp7&Ga+Pwh3L!Njj!-rc;^bTIfo5hP@H##1X8xUZJckrx>id`bAd3QUx9GuomqBYZ!uN1-&o zvTxC?;p8vL67&fW8fw(YOqt>L@bdLrEF*3OgYe$4n4{ zEB40LiU#6-0@5jdN`0w}N0qi@c0~oT2FP z)LNk&a82my?jv(tQpiMi$TK_L@lub#lsM$R{Dk?Ya@%%%huZkct~tSWM714c!45k}-ZLVA-bVM`>|_ZBbW_m-7| z3U%xrAhi}n?T(2F{_n4EZ10inkIFl#y09?7$uwBoJgqY8vylwev)fDOn;>0R!aEnV zBz%j0Mqpx~EZU3q@%+oV7;}|vt7$~ou@faEIq{p?FY$XXg&6*K)b_LP=}gi9`Bij3 zN`zEo|B6*|-;>S`rNa^BKRDbDAk>X#MsR`EvL>6bqU@SaDDs z8>bu@3YdRaWs*Te@G-UHjU%F~kTHw5(0PVJ+pwh#ha2u;DB+UMo@A5UYIl#5rtBV- zGX_hIpw}3C@H*Us(Cc-d#-gNrG#w$(9+S=GxO>3SR`SE2fHZ2KrDc#_C^$jI>Y}#; zMwY=R6@+dWi~0RXw(c@3GZ&%~9K(q&ee0Zw;pwL`E_tZak-#8^_b)Dpyi73^he?xV zXJ08&wh5-M&}qy4f7!D&=E)puDD(Nmg1d_(j`4LvxM5x_huNg-pGG%9rYqO6mImyJ@}*3Y>^3OvcnTG%EV1) zq_Ap?Z!Iw__7#D=pOWnQN$gB!Mr0!9yx|g<4icJh{cFOu3B8}&RiYm+Mb;VEK``LK zL(NcpcTiGieOIssSjr?ob}^``nNf&UcJhXyncO9m{6gD$kqSD`S69(aF8dkWz5>!9 zBLe4Sib7Hs2x_L2Ls6Ish$MGVKrGt5+_2zCyP1byaCg3upo+-I}R4&$m)8 zQ7|jc1Z^VWggpuQj*cP;>Zo9LS!VSzrqmZczaf;u`d0J(f%Z9r%An@s!e>n9%y=n!IZ_tVGu{Jmsbp}Fk%HJIU?a+-~bjfLTuH|JExA8EROowzr zqW9{YyZhR0a4clRK>1I4Ncx&WER~{iE;F^$T7K%X@3PGOA%6#Z%p3TS^&M;Dnjw@i z^o!$9nhcsmcHcY4?4j9+ofL_CWsZ4Hcch(rjsGfGD(nsH>w}^ERqGnz%iGj0j{g}h z7wMkJ-2Z2~eS>2!i}0~B63i;>SyFJU2+>VCS^AxaDOx%g6-t0eM^P<3+*z`ztvOqrG3)&#$K?& z_Y0wbWID47@cU`E1A6A&!`aZk0ZE@z-h#l1NqX2#`$Uev2gepW`rf8*!=rD5&;Jb{ zl08rU>dPo=K%-1Ao1~G-@4ve~y5#9E8x;TE0k5d^TC(=Zc>mwjW^c=+U-<9}b0ku~}gj z3sbW>R2M6DR!g#NUP;nxo>)@7*=RP{U18SDop6b2&PHce^&h97@xx3t+VK+!keE#} z;(Uf&89as9k8{$nkLbuB!-d7TP`_VJpL^Xs8OKB~ri$YUbW8fch64}7|0EWoT(TRj{ z*GT<7Y<7DsrCi79ZsM)z#c(!nNOGySOCkY1fAuQOq12&iUVC!a`#O;dBLf=d?&4*B zI~LgAO7E0qxK(uRTM;IgJ}+z^gD+bi-6I!3x{r9`l~%8TRP%UE0V8E*Sz>Nl1NVG<<7(wDHZ+HcOkQm$O&k+vyx)y)x{Pz!U8hS$*m zByc0h6BUI*BOpuL==P+H|Hx%`>7!W+1H!l9vi&)`V zyn2o9{z=lc+VX*!Vh~SF=)L}Z40XeG>LF6cP^b+R$NxSeUqbK^Q*UTalKzP8X%{9@RSCXm_NhF>{=S2 zi}ezam_^P`S!!-cyEW9y7DBbK93roz@Raccy*v}?mKXScU9E_4g;hBU7}zSofAFda zKYEe?{{I54 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a441313..79eb9d0 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.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index b740cf1..f5feea6 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 +# ############################################################################## # @@ -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 25da30d..9d21a21 100755 --- 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 ########################################################################## diff --git a/patches/api/0001-Force-disable-timings.patch b/patches/api/0001-Force-disable-timings.patch index 50d619a..ff72603 100644 --- a/patches/api/0001-Force-disable-timings.patch +++ b/patches/api/0001-Force-disable-timings.patch @@ -6,48 +6,14 @@ Subject: [PATCH] Force disable timings Need a new profiler system with region threading diff --git a/src/main/java/co/aikar/timings/Timings.java b/src/main/java/co/aikar/timings/Timings.java -index e81d0bc309de877ed2b5da6122f55c162e9b5f10..7760c779e97a0e95d5c3d255b25d949ac20df235 100644 +index 95b7cdf0677ef71e6885fa78aa5c75bb500f5f53..89017af09ce32e7a66014fc3aeb50155921252a5 100644 --- a/src/main/java/co/aikar/timings/Timings.java +++ b/src/main/java/co/aikar/timings/Timings.java -@@ -145,13 +145,14 @@ public final class Timings { +@@ -145,6 +145,7 @@ public final class Timings { * @param enabled Should timings be reported */ public static void setTimingsEnabled(boolean enabled) { + enabled = false; // Folia - region threading - disable timings - timingsEnabled = enabled; - warnAboutDeprecationOnEnable(); - reset(); - } - - private static void warnAboutDeprecationOnEnable() { -- if (timingsEnabled && !warnedAboutDeprecationOnEnable) { -+ if ((true || timingsEnabled) && !warnedAboutDeprecationOnEnable) { // Folia - Bukkit.getLogger().warning(PlainTextComponentSerializer.plainText().serialize(deprecationMessage())); + if (enabled && !warnedAboutDeprecationOnEnable) { + Bukkit.getLogger().severe(PlainTextComponentSerializer.plainText().serialize(deprecationMessage())); warnedAboutDeprecationOnEnable = true; - } -@@ -159,8 +160,8 @@ public final class Timings { - - public static Component deprecationMessage() { - return Component.text() -- .color(TextColor.color(0xffc93a)) -- .append(Component.text("[!] The timings profiler has been enabled but has been scheduled for removal from Paper in the future.")) -+ .color(TextColor.color(0xf39195)) // Folia -+ .append(Component.text("[!] The timings system cannot be enabled on Folia, and has been scheduled for removal from Paper in the future.")) // Folia - .append(Component.newline()) - .append(Component.text(" We recommend migrating to the spark profiler.")) - .append(Component.newline()) -diff --git a/src/main/java/co/aikar/timings/TimingsCommand.java b/src/main/java/co/aikar/timings/TimingsCommand.java -index 95d87c9dbf2b237787294dfbe7fed87a36e6dedf..b83e5ff7ada8771fdf27ba9807c77ba6a4ce12da 100644 ---- a/src/main/java/co/aikar/timings/TimingsCommand.java -+++ b/src/main/java/co/aikar/timings/TimingsCommand.java -@@ -56,8 +56,9 @@ public class TimingsCommand extends BukkitCommand { - if (!testPermission(sender)) { - return true; - } -- if (false) { -+ if (true) { - sender.sendMessage(Timings.deprecationMessage()); -+ return true; - } - if (args.length < 1) { - sender.sendMessage(text("Usage: " + this.usageMessage, NamedTextColor.RED)); diff --git a/patches/api/0002-Region-scheduler-API.patch b/patches/api/0002-Region-scheduler-API.patch index 232908d..19f59bf 100644 --- a/patches/api/0002-Region-scheduler-API.patch +++ b/patches/api/0002-Region-scheduler-API.patch @@ -7,7 +7,7 @@ Add both a location based scheduler, an entity based scheduler, and a global region scheduler. diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 003bece642b682985625db93cad93026352bfc66..065352b383d6398382b4f14641859dbfe2e6a355 100644 +index b878e7167cfcdea0e224c182b40abeadd339d3b3..9611e8e254b4fa9579dc9ffd5198182c43819c56 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -557,9 +557,9 @@ public final class SimplePluginManager implements PluginManager { diff --git a/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch b/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch deleted file mode 100644 index a6cb57f..0000000 --- a/patches/api/0005-Add-API-for-checking-ownership-of-region-by-position.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Tue, 7 Mar 2023 14:34:09 -0800 -Subject: [PATCH] Add API for checking ownership of region by position/entity - -This may be useful for plugins which want to perform operations -over large areas outside of the buffer zone provided by the -regionaliser, as it is not guaranteed that anything outside -of the buffer zone is owned. Then, the plugins may use -the schedulers depending on the result of the ownership -check. - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index e20e4239a5a1f952e1c70e899549989d5e42f73c..60ac226b58981155649b7d67c11385a0c105eca0 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2916,6 +2916,14 @@ public final class Bukkit { - return server.isOwnedByCurrentRegion(entity); - } - // Paper end - Folia region threading API -+ // Folia start - region threading API -+ /** -+ * Returns whether the current thread is ticking the global region. -+ */ -+ public static boolean isGlobalTickThread() { -+ return server.isGlobalTickThread(); -+ } -+ // Folia end - region threading API - - @NotNull - public static Server.Spigot spigot() { -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 6246251caf2c6f025c824b8e7a944b8d48751fa1..10f6eb1756de71960f1c0565366d5f262c7641f1 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -2554,4 +2554,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - */ - boolean isOwnedByCurrentRegion(@NotNull Entity entity); - // Paper end - Folia region threading API -+ // Folia start - region threading API -+ /** -+ * Returns whether the current thread is ticking the global region. -+ */ -+ public boolean isGlobalTickThread(); -+ // Folia end - region threading API - } diff --git a/patches/server/0001-Build-changes.patch b/patches/server/0001-Build-changes.patch index 498d298..850dc53 100644 --- a/patches/server/0001-Build-changes.patch +++ b/patches/server/0001-Build-changes.patch @@ -5,19 +5,19 @@ Subject: [PATCH] Build changes diff --git a/build.gradle.kts b/build.gradle.kts -index de0474b8dce58cb419c00b7614d7dd66be832a02..c2f2ba1df68e9823c56287f1bea23fb6d6a781a2 100644 +index faf3e3fd72e8c915e7a4803dacbe1bb576c6663e..142714c7d47eb5de937ad385c81968148a7e4828 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -13,7 +13,7 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { - val alsoShade: Configuration by configurations.creating +@@ -25,7 +25,7 @@ abstract class MockitoAgentProvider : CommandLineArgumentProvider { + // Paper end - configure mockito agent that is needed in newer java versions dependencies { - implementation(project(":paper-api")) + implementation(project(":folia-api")) // Folia // Paper start - implementation("org.jline:jline-terminal-jansi:3.21.0") - implementation("net.minecrell:terminalconsoleappender:1.3.0") -@@ -85,14 +85,14 @@ tasks.jar { + implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+ + implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21 +@@ -99,14 +99,14 @@ tasks.jar { val gitBranch = git("rev-parse", "--abbrev-ref", "HEAD").getText().trim() // Paper attributes( "Main-Class" to "org.bukkit.craftbukkit.Main", @@ -36,7 +36,7 @@ index de0474b8dce58cb419c00b7614d7dd66be832a02..c2f2ba1df68e9823c56287f1bea23fb6 "Build-Number" to (build ?: ""), "Build-Time" to Instant.now().toString(), "Git-Branch" to gitBranch, // Paper -@@ -153,7 +153,7 @@ fun TaskContainer.registerRunTask( +@@ -172,7 +172,7 @@ fun TaskContainer.registerRunTask( name: String, block: JavaExec.() -> Unit ): TaskProvider = register(name) { diff --git a/patches/server/0003-Threaded-Regions.patch b/patches/server/0003-Threaded-Regions.patch index 7e9b694..496e9bf 100644 --- a/patches/server/0003-Threaded-Regions.patch +++ b/patches/server/0003-Threaded-Regions.patch @@ -7,10 +7,10 @@ See https://docs.papermc.io/folia/reference/overview and https://docs.papermc.io/folia/reference/region-logic diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java b/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java -index 0abba00741b39b69a7f167e5d2670f2565c9a752..83b052dbf6d21775664b286518f3cef1d86e87d1 100644 +index fc029c8fb22a7c8eeb23bfc171812f6da91c60fa..e1aba122e1c3d8b28ca16137fb15bcee07cdf0e7 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/ChunkSystem.java -@@ -72,11 +72,15 @@ public final class ChunkSystem { +@@ -78,17 +78,22 @@ public final class ChunkSystem { } public static void onChunkHolderCreate(final ServerLevel level, final ChunkHolder holder) { @@ -21,14 +21,21 @@ index 0abba00741b39b69a7f167e5d2670f2565c9a752..83b052dbf6d21775664b286518f3cef1 } public static void onChunkHolderDelete(final ServerLevel level, final ChunkHolder holder) { -- + // Update progress listener for LevelLoadingScreen +- final ChunkProgressListener progressListener = level.getChunkSource().chunkMap.progressListener; ++ final ChunkProgressListener progressListener = null; // Folia - threaded regions - cannot schedule chunk task here; as it would create a chunkholder + if (progressListener != null) { + ChunkSystem.scheduleChunkTask(level, holder.getPos().x, holder.getPos().z, () -> { + progressListener.onStatusChange(holder.getPos(), null); + }); + } + // Folia start - threaded regions + level.regioniser.removeChunk(holder.getPos().x, holder.getPos().z); + // Folia end - threaded regions } public static void onChunkPreBorder(final LevelChunk chunk, final ChunkHolder holder) { -@@ -85,16 +89,12 @@ public final class ChunkSystem { +@@ -97,16 +102,12 @@ public final class ChunkSystem { } public static void onChunkBorder(final LevelChunk chunk, final ChunkHolder holder) { @@ -47,7 +54,7 @@ index 0abba00741b39b69a7f167e5d2670f2565c9a752..83b052dbf6d21775664b286518f3cef1 chunk.unloadCallback(); } -@@ -104,9 +104,7 @@ public final class ChunkSystem { +@@ -116,9 +117,7 @@ public final class ChunkSystem { } public static void onChunkTicking(final LevelChunk chunk, final ChunkHolder holder) { @@ -56,9 +63,9 @@ index 0abba00741b39b69a7f167e5d2670f2565c9a752..83b052dbf6d21775664b286518f3cef1 - ); + chunk.getLevel().getCurrentWorldData().addTickingChunk(chunk.moonrise$getChunkAndHolder()); // Folia - region threading if (!((ChunkSystemLevelChunk)chunk).moonrise$isPostProcessingDone()) { - chunk.postProcessGeneration(); + chunk.postProcessGeneration((ServerLevel)chunk.getLevel()); } -@@ -115,21 +113,15 @@ public final class ChunkSystem { +@@ -128,22 +127,16 @@ public final class ChunkSystem { } public static void onChunkNotTicking(final LevelChunk chunk, final ChunkHolder holder) { @@ -66,6 +73,7 @@ index 0abba00741b39b69a7f167e5d2670f2565c9a752..83b052dbf6d21775664b286518f3cef1 - ((ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder() - ); + chunk.getLevel().getCurrentWorldData().removeTickingChunk(chunk.moonrise$getChunkAndHolder()); // Folia - region threading + ((ChunkTickServerLevel)(ServerLevel)chunk.getLevel()).moonrise$removeChunkForPlayerTicking(chunk); // Moonrise - chunk tick iteration } public static void onChunkEntityTicking(final LevelChunk chunk, final ChunkHolder holder) { @@ -84,7 +92,7 @@ index 0abba00741b39b69a7f167e5d2670f2565c9a752..83b052dbf6d21775664b286518f3cef1 public static ChunkHolder getUnloadingChunkHolder(final ServerLevel level, final int chunkX, final int chunkZ) { diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java -index 11b7f15755dde766140c29bedca456c80d53293f..7d626bec6f0a4497026de6c0311e27cf95cfd757 100644 +index 217d1f908a36a5177ba3cbb80a33f73d4dab0fa0..301cc1c0d91f5e755f74ace60dbe5551240b496d 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java @@ -1,5 +1,11 @@ @@ -99,7 +107,7 @@ index 11b7f15755dde766140c29bedca456c80d53293f..7d626bec6f0a4497026de6c0311e27cf import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.ChunkPos; -@@ -94,46 +100,149 @@ public class TickThread extends Thread { +@@ -98,46 +104,149 @@ public class TickThread extends Thread { } public static boolean isShutdownThread() { @@ -261,7 +269,7 @@ index 11b7f15755dde766140c29bedca456c80d53293f..7d626bec6f0a4497026de6c0311e27cf } } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java -index efc0c1acc8239dd7b00211a1d3bfd3fc3b2c810c..d13902e58c9bf6b25469a432bb87230da98b9d12 100644 +index 93335de8cf514dc8417e4b9b2d495663deda2904..404081147b504ebc6d0dba8bbf37dc4fba309eb0 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java @@ -460,6 +460,19 @@ public abstract class EntityLookup implements LevelEntityGetter { @@ -273,7 +281,7 @@ index efc0c1acc8239dd7b00211a1d3bfd3fc3b2c810c..d13902e58c9bf6b25469a432bb87230d + public boolean addEntityForShutdownTeleportComplete(final Entity entity) { + final BlockPos pos = entity.blockPosition(); + final int sectionX = pos.getX() >> 4; -+ final int sectionY = Mth.clamp(pos.getY() >> 4, this.minSection, this.maxSection); ++ final int sectionY = Mth.clamp(pos.getY() >> 4, WorldUtil.getMinSection(this.world), WorldUtil.getMaxSection(this.world)); + final int sectionZ = pos.getZ() >> 4; + final ChunkEntitySlices slices = this.getOrCreateChunk(sectionX, sectionZ); + @@ -294,28 +302,20 @@ index efc0c1acc8239dd7b00211a1d3bfd3fc3b2c810c..d13902e58c9bf6b25469a432bb87230d } } -@@ -1080,4 +1096,4 @@ public abstract class EntityLookup implements LevelEntityGetter { - @Override - public void onRemove(final Entity.RemovalReason reason) {} - } --} -\ No newline at end of file -+} diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java -index dacf2b2988ce603879fe525a3418ac77f8a663f7..e479cea245b0a345c46c9bb5fd9d86afba6fd77e 100644 +index 58d9187adc188b693b6becc400f766e069bf1bf5..2b44515cede7dfa6d8dbfd469e53632b41dc1c21 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java -@@ -16,8 +16,7 @@ public final class ServerEntityLookup extends EntityLookup { +@@ -18,7 +18,7 @@ public final class ServerEntityLookup extends EntityLookup { private static final Entity[] EMPTY_ENTITY_ARRAY = new Entity[0]; private final ServerLevel serverWorld; - public final ReferenceList trackerEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker -- public final ReferenceList trackerUnloadedEntities = new ReferenceList<>(EMPTY_ENTITY_ARRAY); // Moonrise - entity tracker + // Folia - move to regionized world data public ServerEntityLookup(final ServerLevel world, final LevelCallback worldCallback) { super(world, worldCallback); -@@ -70,6 +69,7 @@ public final class ServerEntityLookup extends EntityLookup { +@@ -76,6 +76,7 @@ public final class ServerEntityLookup extends EntityLookup { if (entity instanceof ServerPlayer player) { ((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().addPlayer(player); } @@ -323,21 +323,12 @@ index dacf2b2988ce603879fe525a3418ac77f8a663f7..e479cea245b0a345c46c9bb5fd9d86af } @Override -@@ -77,22 +77,22 @@ public final class ServerEntityLookup extends EntityLookup { - if (entity instanceof ServerPlayer player) { - ((ChunkSystemServerLevel)this.serverWorld).moonrise$getNearbyPlayers().removePlayer(player); - } -- this.trackerUnloadedEntities.remove(entity); // Moonrise - entity tracker -+ this.world.getCurrentWorldData().trackerUnloadedEntities.remove(entity); // Moonrise - entity tracker // Folia - region threading - } - +@@ -88,14 +89,14 @@ public final class ServerEntityLookup extends EntityLookup { @Override protected void entityStartLoaded(final Entity entity) { // Moonrise start - entity tracker - this.trackerEntities.add(entity); -- this.trackerUnloadedEntities.remove(entity); + this.world.getCurrentWorldData().trackerEntities.add(entity); // Folia - region threading -+ this.world.getCurrentWorldData().trackerUnloadedEntities.remove(entity); // Folia - region threading // Moonrise end - entity tracker } @@ -345,17 +336,15 @@ index dacf2b2988ce603879fe525a3418ac77f8a663f7..e479cea245b0a345c46c9bb5fd9d86af protected void entityEndLoaded(final Entity entity) { // Moonrise start - entity tracker - this.trackerEntities.remove(entity); -- this.trackerUnloadedEntities.add(entity); + this.world.getCurrentWorldData().trackerEntities.remove(entity); // Folia - region threading -+ this.world.getCurrentWorldData().trackerUnloadedEntities.add(entity); // Folia - region threading // Moonrise end - entity tracker } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java -index a608f57ebca98eda88ad749d0aad021678be54f9..433abf4237f698872db0e07d92b680408109d470 100644 +index 5a6defc4c4d30c06d4bba856847feb176950ca1e..65e4e94b97bae13115f141a459159e9db1ec9a9a 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/player/RegionizedPlayerChunkLoader.java -@@ -213,7 +213,7 @@ public final class RegionizedPlayerChunkLoader { +@@ -214,7 +214,7 @@ public final class RegionizedPlayerChunkLoader { final PlayerChunkLoaderData loader = ((ChunkSystemServerPlayer)player).moonrise$getChunkLoader(); if (loader == null) { @@ -364,7 +353,7 @@ index a608f57ebca98eda88ad749d0aad021678be54f9..433abf4237f698872db0e07d92b68040 } loader.remove(); -@@ -301,7 +301,7 @@ public final class RegionizedPlayerChunkLoader { +@@ -302,7 +302,7 @@ public final class RegionizedPlayerChunkLoader { public void tick() { TickThread.ensureTickThread("Cannot tick player chunk loader async"); long currTime = System.nanoTime(); @@ -425,10 +414,10 @@ index 7eafc5b7cba23d8dec92ecc1050afe3fd8c9e309..4bfcae47ed76346e6200514ebce5b04f \ No newline at end of file +} diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd677cd937 100644 +index 91a6f57f35fc1553159cca138a0619e703b2b014..3a476713964002734a9e67fd9b6dfa497b590657 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -@@ -56,6 +56,14 @@ import java.util.concurrent.atomic.AtomicReference; +@@ -57,6 +57,14 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.LockSupport; import java.util.function.Predicate; @@ -443,7 +432,7 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd public final class ChunkHolderManager { private static final Logger LOGGER = LogUtils.getClassLogger(); -@@ -78,29 +86,83 @@ public final class ChunkHolderManager { +@@ -79,29 +87,83 @@ public final class ChunkHolderManager { private final ConcurrentLong2ReferenceChainedHashTable chunkHolders = ConcurrentLong2ReferenceChainedHashTable.createWithCapacity(16384, 0.25f); private final ServerLevel world; private final ChunkTaskScheduler taskScheduler; @@ -455,7 +444,11 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd + if (c1 == c2) { + return 0; + } -+ + +- private final ArrayDeque pendingFullLoadUpdate = new ArrayDeque<>(); +- private final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((final NewChunkHolder c1, final NewChunkHolder c2) -> { +- if (c1 == c2) { +- return 0; + final int saveTickCompare = Long.compare(c1.lastAutoSave, c2.lastAutoSave); + + if (saveTickCompare != 0) { @@ -464,11 +457,7 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd + + final long coord1 = CoordinateUtils.getChunkKey(c1.chunkX, c1.chunkZ); + final long coord2 = CoordinateUtils.getChunkKey(c2.chunkX, c2.chunkZ); - -- private final ArrayDeque pendingFullLoadUpdate = new ArrayDeque<>(); -- private final ObjectRBTreeSet autoSaveQueue = new ObjectRBTreeSet<>((final NewChunkHolder c1, final NewChunkHolder c2) -> { -- if (c1 == c2) { -- return 0; ++ + if (coord1 == coord2) { + throw new IllegalStateException("Duplicate chunkholder in auto save queue"); + } @@ -501,13 +490,13 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd + data.pendingFullLoadUpdate.add(fullLoadUpdate); + } // else: fullLoadUpdate is an unloaded chunk holder + } -+ -+ for (final NewChunkHolder autoSave : this.autoSaveQueue) { -+ final int regionCoordinateX = autoSave.chunkX >> chunkToRegionShift; -+ final int regionCoordinateZ = autoSave.chunkZ >> chunkToRegionShift; - if (saveTickCompare != 0) { - return saveTickCompare; ++ for (final NewChunkHolder autoSave : this.autoSaveQueue) { ++ final int regionCoordinateX = autoSave.chunkX >> chunkToRegionShift; ++ final int regionCoordinateZ = autoSave.chunkZ >> chunkToRegionShift; ++ + final HolderManagerRegionData data = regionToData.get(CoordinateUtils.getChunkKey(regionCoordinateX, regionCoordinateZ)); + if (data != null) { + data.autoSaveQueue.add(autoSave); @@ -541,7 +530,7 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd public ChunkHolderManager(final ServerLevel world, final ChunkTaskScheduler taskScheduler) { this.world = world; -@@ -185,8 +247,13 @@ public final class ChunkHolderManager { +@@ -186,8 +248,13 @@ public final class ChunkHolderManager { } public void close(final boolean save, final boolean halt) { @@ -552,11 +541,11 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd + // Folia end - region threading TickThread.ensureTickThread("Closing world off-main"); - if (halt) { -+ if (halt && halt) { // Folia - region threading ++ if (first && halt) { // Folia - region threading LOGGER.info("Waiting 60s for chunk system to halt for world '" + WorldUtil.getWorldName(this.world) + "'"); if (!this.taskScheduler.halt(true, TimeUnit.SECONDS.toNanos(60L))) { - LOGGER.warn("Failed to halt world generation/loading tasks for world '" + WorldUtil.getWorldName(this.world) + "'"); -@@ -196,9 +263,10 @@ public final class ChunkHolderManager { + LOGGER.warn("Failed to halt generation/loading tasks for world '" + WorldUtil.getWorldName(this.world) + "'"); +@@ -197,9 +264,10 @@ public final class ChunkHolderManager { } if (save) { @@ -565,10 +554,10 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd } + if (last) { // Folia - region threading - boolean hasTasks = false; - for (final RegionFileIOThread.RegionFileType type : RegionFileIOThread.RegionFileType.values()) { - if (RegionFileIOThread.getControllerFor(this.world, type).hasTasks()) { -@@ -218,28 +286,35 @@ public final class ChunkHolderManager { + MoonriseRegionFileIO.flush(this.world); + + if (halt) { +@@ -219,28 +287,35 @@ public final class ChunkHolderManager { LOGGER.error("Failed to close '" + type.name() + "' regionfile cache for world '" + WorldUtil.getWorldName(this.world) + "'", ex); } } @@ -592,8 +581,8 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd final List reschedule = new ArrayList<>(); - final long currentTick = this.currentTick; + final long currentTick = RegionizedServer.getCurrentTick(); // Folia - region threading - final long maxSaveTime = currentTick - Math.max(1L, this.world.paperConfig().chunks.autoSaveInterval.value()); - final int maxToSave = this.world.paperConfig().chunks.maxAutoSaveChunksPerTick; + final long maxSaveTime = currentTick - Math.max(1L, PlatformHooks.get().configAutoSaveInterval(this.world)); + final int maxToSave = PlatformHooks.get().configMaxAutoSavePerTick(this.world); - for (int autoSaved = 0; autoSaved < maxToSave && !this.autoSaveQueue.isEmpty();) { - final NewChunkHolder holder = this.autoSaveQueue.first(); + // Folia start - region threading @@ -611,7 +600,7 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd holder.lastAutoSave = currentTick; if (holder.save(false) != null) { -@@ -253,15 +328,38 @@ public final class ChunkHolderManager { +@@ -254,15 +329,38 @@ public final class ChunkHolderManager { for (final NewChunkHolder holder : reschedule) { if (holder.getChunkStatus().isOrAfter(FullChunkStatus.FULL)) { @@ -631,9 +620,9 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd + // we could iterate through all chunk holders with thread checks, however for many regions the iteration cost alone + // will multiply. to avoid this, we can simply iterate through all owned sections + final int regionShift = this.world.moonrise$getRegionChunkShift(); ++ final int width = 1 << regionShift; + for (final LongIterator iterator = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegion().getOwnedSectionsUnsynchronised(); iterator.hasNext();) { + final long sectionKey = iterator.nextLong(); -+ final int width = 1 << regionShift; + final int offsetX = CoordinateUtils.getChunkX(sectionKey) << regionShift; + final int offsetZ = CoordinateUtils.getChunkZ(sectionKey) << regionShift; + @@ -653,8 +642,8 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd LOGGER.info("Saving all chunkholders for world '" + WorldUtil.getWorldName(this.world) + "'"); } -@@ -280,6 +378,12 @@ public final class ChunkHolderManager { - +@@ -291,6 +389,12 @@ public final class ChunkHolderManager { + } for (int i = 0, len = holders.size(); i < len; ++i) { final NewChunkHolder holder = holders.get(i); + // Folia start - region threading @@ -666,16 +655,16 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd try { final NewChunkHolder.SaveStat saveStat = holder.save(shutdown); if (saveStat != null) { -@@ -310,7 +414,7 @@ public final class ChunkHolderManager { +@@ -326,7 +430,7 @@ public final class ChunkHolderManager { } } } - if (flush) { + if (last && flush) { // Folia - region threading - RegionFileIOThread.flush(); + MoonriseRegionFileIO.flush(this.world); try { - RegionFileIOThread.flushRegionStorages(this.world); -@@ -711,7 +815,13 @@ public final class ChunkHolderManager { + MoonriseRegionFileIO.flushRegionStorages(this.world); +@@ -731,7 +835,13 @@ public final class ChunkHolderManager { } public void tick() { @@ -690,7 +679,7 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd final int sectionShift = ((ChunkSystemServerLevel)this.world).moonrise$getRegionChunkShift(); -@@ -725,7 +835,7 @@ public final class ChunkHolderManager { +@@ -745,7 +855,7 @@ public final class ChunkHolderManager { return removeDelay <= 0L; }; @@ -699,7 +688,7 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd final long sectionKey = iterator.nextLong(); if (!this.sectionToChunkToExpireCount.containsKey(sectionKey)) { -@@ -1010,26 +1120,58 @@ public final class ChunkHolderManager { +@@ -1030,26 +1140,56 @@ public final class ChunkHolderManager { if (changedFullStatus.isEmpty()) { return; } @@ -711,7 +700,7 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd - } - ChunkHolderManager.this.processPendingFullUpdate(); -- }, PrioritisedExecutor.Priority.HIGHEST); +- }, Priority.HIGHEST); - } else { - final ArrayDeque pendingFullLoadUpdate = this.pendingFullLoadUpdate; - for (int i = 0, len = changedFullStatus.size(); i < len; ++i) { @@ -738,9 +727,6 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd + }).add(holder); + } + } -+ // Folia end - region threading -+ -+ // Folia start - region threading + if (!thisRegionHolders.isEmpty()) { + thisRegion.getData().getHolderManagerRegionData().pendingFullLoadUpdate.addAll(thisRegionHolders); + } @@ -755,23 +741,24 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd + final int chunkZ = CoordinateUtils.getChunkZ(sectionKey) << regionShift; + + final List regionHolders = entry.getValue(); -+ this.taskScheduler.scheduleChunkTaskEventually(chunkX, chunkZ, () -> { // Folia - region threading ++ this.taskScheduler.scheduleChunkTaskEventually(chunkX, chunkZ, () -> { + ChunkHolderManager.this.getCurrentRegionData().pendingFullLoadUpdate.addAll(regionHolders); + ChunkHolderManager.this.processPendingFullUpdate(); -+ }, PrioritisedExecutor.Priority.HIGHEST); -+ // Folia end - region threading ++ }, Priority.HIGHEST); ++ } } ++ // Folia end - region threading } private void removeChunkHolder(final NewChunkHolder holder) { - holder.markUnloaded(); + holder.onUnload(); - this.autoSaveQueue.remove(holder); + this.getCurrentRegionData().autoSaveQueue.remove(holder); // Folia - region threading ChunkSystem.onChunkHolderDelete(this.world, holder.vanillaChunkHolder); this.chunkHolders.remove(CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ)); - -@@ -1043,7 +1185,7 @@ public final class ChunkHolderManager { + } +@@ -1062,7 +1202,7 @@ public final class ChunkHolderManager { throw new IllegalStateException("Cannot unload chunks recursively"); } final int sectionShift = this.unloadQueue.coordinateShift; // sectionShift <= lock shift @@ -780,7 +767,7 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd int unloadCountTentative = 0; for (final ChunkUnloadQueue.SectionToUnload sectionRef : unloadSectionsForRegion) { final ChunkUnloadQueue.UnloadSection section -@@ -1353,7 +1495,13 @@ public final class ChunkHolderManager { +@@ -1380,7 +1520,13 @@ public final class ChunkHolderManager { // only call on tick thread private boolean processPendingFullUpdate() { @@ -795,7 +782,7 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd boolean ret = false; -@@ -1364,9 +1512,7 @@ public final class ChunkHolderManager { +@@ -1391,9 +1537,7 @@ public final class ChunkHolderManager { ret |= holder.handleFullStatusChange(changedFullStatus); if (!changedFullStatus.isEmpty()) { @@ -807,24 +794,24 @@ index 58d3d1a47e9f2423c467bb329c2d5f4b58a8b5ef..4b36209f016b025087da359ab49e44bd } } diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java -index 8671a90e969d16c7a57ddc38fedb7cf01815f64c..085d035b5d127d14af6b8487bee5446b814bc590 100644 +index b0bfe655922877676948d9b6ff3fa5a6ebb7a640..9b49234ae3c15585e4d8081a9cbd4388b1624c8d 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java -@@ -157,7 +157,7 @@ public final class ChunkTaskScheduler { - private final PrioritisedThreadPool.PrioritisedPoolExecutor radiusAwareGenExecutor; - public final PrioritisedThreadPool.PrioritisedPoolExecutor loadExecutor; +@@ -122,7 +122,7 @@ public final class ChunkTaskScheduler { + public final PrioritisedThreadPool.ExecutorGroup.ThreadPoolExecutor compressionExecutor; + public final PrioritisedThreadPool.ExecutorGroup.ThreadPoolExecutor saveExecutor; -- private final PrioritisedThreadedTaskQueue mainThreadExecutor = new PrioritisedThreadedTaskQueue(); +- private final PrioritisedTaskQueue mainThreadExecutor = new PrioritisedTaskQueue(); + // Folia - regionised ticking public final ChunkHolderManager chunkHolderManager; -@@ -360,14 +360,13 @@ public final class ChunkTaskScheduler { +@@ -327,14 +327,13 @@ public final class ChunkTaskScheduler { }; // this may not be good enough, specifically thanks to stupid ass plugins swallowing exceptions -- this.scheduleChunkTask(chunkX, chunkZ, crash, PrioritisedExecutor.Priority.BLOCKING); -+ this.scheduleChunkTaskEventually(chunkX, chunkZ, crash, PrioritisedExecutor.Priority.BLOCKING); // Folia - region threading +- this.scheduleChunkTask(chunkX, chunkZ, crash, Priority.BLOCKING); ++ this.scheduleChunkTaskEventually(chunkX, chunkZ, crash, Priority.BLOCKING); // Folia - region threading // so, make the main thread pick it up ((ChunkSystemMinecraftServer)this.world.getServer()).moonrise$setChunkSystemCrash(new RuntimeException("Chunk system crash propagated from unrecoverableChunkSystemFailure", reportedException)); } @@ -835,92 +822,72 @@ index 8671a90e969d16c7a57ddc38fedb7cf01815f64c..085d035b5d127d14af6b8487bee5446b + throw new UnsupportedOperationException("Use regionised ticking hooks"); // Folia - regionised ticking } - public void raisePriority(final int x, final int z, final PrioritisedExecutor.Priority priority) { -@@ -607,7 +606,7 @@ public final class ChunkTaskScheduler { - this.chunkHolderManager.processTicketUpdates(); - } - -- final Consumer loadCallback = (final ChunkAccess chunk) -> { -+ final Consumer loadCallback = onComplete == null && !addTicket ? null : (final ChunkAccess chunk) -> { - try { - if (onComplete != null) { - onComplete.accept(chunk); -@@ -644,7 +643,9 @@ public final class ChunkTaskScheduler { - if (!chunkHolder.upgradeGenTarget(toStatus)) { - this.schedule(chunkX, chunkZ, toStatus, chunkHolder, tasks); - } -- chunkHolder.addStatusConsumer(toStatus, loadCallback); -+ if (loadCallback != null) { -+ chunkHolder.addStatusConsumer(toStatus, loadCallback); -+ } - } - } - } finally { -@@ -658,7 +659,7 @@ public final class ChunkTaskScheduler { - tasks.get(i).schedule(); - } - -- if (!scheduled) { -+ if (loadCallback != null && !scheduled) { - // couldn't schedule - try { - loadCallback.accept(chunk); -@@ -830,7 +831,7 @@ public final class ChunkTaskScheduler { + public void raisePriority(final int x, final int z, final Priority priority) { +@@ -812,7 +811,7 @@ public final class ChunkTaskScheduler { */ @Deprecated - public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final Runnable run) { -- return this.scheduleChunkTask(run, PrioritisedExecutor.Priority.NORMAL); -+ throw new UnsupportedOperationException(); // Folia - regionised ticking - } - - /** -@@ -838,7 +839,7 @@ public final class ChunkTaskScheduler { - */ - @Deprecated - public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final Runnable run, final PrioritisedExecutor.Priority priority) { -- return this.mainThreadExecutor.queueRunnable(run, priority); + public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final Runnable run, final Priority priority) { +- return this.mainThreadExecutor.queueTask(run, priority); + throw new UnsupportedOperationException(); // Folia - regionised ticking } public PrioritisedExecutor.PrioritisedTask createChunkTask(final int chunkX, final int chunkZ, final Runnable run) { -@@ -847,7 +848,7 @@ public final class ChunkTaskScheduler { +@@ -821,7 +820,7 @@ public final class ChunkTaskScheduler { public PrioritisedExecutor.PrioritisedTask createChunkTask(final int chunkX, final int chunkZ, final Runnable run, - final PrioritisedExecutor.Priority priority) { + final Priority priority) { - return this.mainThreadExecutor.createTask(run, priority); -+ return MinecraftServer.getServer().regionizedServer.taskQueue.createChunkTask(this.world, chunkX, chunkZ, run, priority); // Folia - regionised ticking ++ return io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.createChunkTask(this.world, chunkX, chunkZ, run, priority); // Folia - regionised ticking } public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final int chunkX, final int chunkZ, final Runnable run) { -@@ -856,8 +857,22 @@ public final class ChunkTaskScheduler { +@@ -830,9 +829,27 @@ public final class ChunkTaskScheduler { public PrioritisedExecutor.PrioritisedTask scheduleChunkTask(final int chunkX, final int chunkZ, final Runnable run, - final PrioritisedExecutor.Priority priority) { -- return this.mainThreadExecutor.queueRunnable(run, priority); -+ return MinecraftServer.getServer().regionizedServer.taskQueue.queueChunkTask(this.world, chunkX, chunkZ, run, priority); // Folia - regionised ticking -+ } -+ + final Priority priority) { +- return this.mainThreadExecutor.queueTask(run, priority); ++ return io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueChunkTask(this.world, chunkX, chunkZ, run, priority); // Folia - regionised ticking + } + + // Folia start - region threading + // this function is guaranteed to never touch the ticket lock or schedule lock + // yes, this IS a hack so that we can avoid deadlock due to region threading introducing the + // ticket lock in the schedule logic ++ public PrioritisedExecutor.PrioritisedTask scheduleChunkTaskEventually(final int chunkX, final int chunkZ, final Runnable run) { ++ return this.scheduleChunkTaskEventually(chunkX, chunkZ, run, Priority.NORMAL); ++ } ++ + public PrioritisedExecutor.PrioritisedTask scheduleChunkTaskEventually(final int chunkX, final int chunkZ, final Runnable run, -+ final PrioritisedExecutor.Priority priority) { ++ final Priority priority) { + final PrioritisedExecutor.PrioritisedTask ret = this.createChunkTask(chunkX, chunkZ, run, priority); + this.world.taskQueueRegionData.pushGlobalChunkTask(() -> { -+ MinecraftServer.getServer().regionizedServer.taskQueue.queueChunkTask(ChunkTaskScheduler.this.world, chunkX, chunkZ, run, priority); ++ io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueChunkTask(ChunkTaskScheduler.this.world, chunkX, chunkZ, run, priority); + }); + return ret; - } ++ } + // Folia end - region threading - ++ public boolean halt(final boolean sync, final long maxWaitNS) { this.radiusAwareGenExecutor.halt(); + this.parallelGenExecutor.halt(); diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java -index 45eda96fd8a1acb87dbb69ce5495fec7e451416f..3210d4cb97301d6fa5ffe76fd7c263ab7aa0a8be 100644 +index eafa4e6d55cd0f9314ac0f2b96a7f48fbb5e1a4c..9e7e10fe46dbbd03d690a65af6ae719d1665bc6a 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java -@@ -1378,7 +1378,7 @@ public final class NewChunkHolder { +@@ -1360,10 +1360,10 @@ public final class NewChunkHolder { + private void completeStatusConsumers(ChunkStatus status, final ChunkAccess chunk) { + // Update progress listener for LevelLoadingScreen + if (chunk != null) { +- final ChunkProgressListener progressListener = this.world.getChunkSource().chunkMap.progressListener; ++ final ChunkProgressListener progressListener = null; // Folia - threaded regions + if (progressListener != null) { + final ChunkStatus finalStatus = status; +- this.scheduler.scheduleChunkTask(this.chunkX, this.chunkZ, () -> { ++ this.scheduler.scheduleChunkTaskEventually(this.chunkX, this.chunkZ, () -> { // Folia - threaded regions + progressListener.onStatusChange(this.vanillaChunkHolder.getPos(), finalStatus); + }); + } +@@ -1384,7 +1384,7 @@ public final class NewChunkHolder { } // must be scheduled to main, we do not trust the callback to not do anything stupid @@ -929,7 +896,7 @@ index 45eda96fd8a1acb87dbb69ce5495fec7e451416f..3210d4cb97301d6fa5ffe76fd7c263ab for (final Consumer consumer : consumers) { try { consumer.accept(chunk); -@@ -1406,7 +1406,7 @@ public final class NewChunkHolder { +@@ -1412,7 +1412,7 @@ public final class NewChunkHolder { } // must be scheduled to main, we do not trust the callback to not do anything stupid @@ -939,23 +906,23 @@ index 45eda96fd8a1acb87dbb69ce5495fec7e451416f..3210d4cb97301d6fa5ffe76fd7c263ab try { consumer.accept(chunk); diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java b/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java -index 748ab4d637ce463272bae4fdbab6842a27385126..8e2a3d85b7fb78d4e7198c09f356acb51f5be1e0 100644 +index aec503ca1551ce4b15b8975832cd664ebd670722..bf6b5e251bd8e5702e21cac2052ba53d38bfdf0c 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/collisions/CollisionUtil.java -@@ -1628,7 +1628,7 @@ public final class CollisionUtil { +@@ -1967,7 +1967,7 @@ public final class CollisionUtil { for (int currChunkZ = minChunkZ; currChunkZ <= maxChunkZ; ++currChunkZ) { for (int currChunkX = minChunkX; currChunkX <= maxChunkX; ++currChunkX) { -- final net.minecraft.world.level.chunk.ChunkAccess chunk = chunkSource.getChunk(currChunkX, currChunkZ, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, loadChunks); -+ final net.minecraft.world.level.chunk.ChunkAccess chunk = !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)world, currChunkX, currChunkZ) ? null : chunkSource.getChunk(currChunkX, currChunkZ, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, loadChunks); // Folia - region threading +- final ChunkAccess chunk = chunkSource.getChunk(currChunkX, currChunkZ, ChunkStatus.FULL, loadChunks); ++ final ChunkAccess chunk = !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)world, currChunkX, currChunkZ) ? null : chunkSource.getChunk(currChunkX, currChunkZ, ChunkStatus.FULL, loadChunks); // Folia - region threading if (chunk == null) { if ((collisionFlags & COLLISION_FLAG_COLLIDE_WITH_UNLOADED_CHUNKS) != 0) { diff --git a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java -index 9f17170179cc99d84ad25a1e838aff3d8cc66f93..780c31121ea62d986fe6918c095f61797083d1da 100644 +index e7d510af3e415064fd483f0220d5f6a4cd0b9f63..8bc53743698df06cc31365e82c211257cfff6a82 100644 --- a/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java +++ b/src/main/java/com/destroystokyo/paper/util/RedstoneWireTurbo.java -@@ -833,14 +833,14 @@ public class RedstoneWireTurbo { +@@ -836,14 +836,14 @@ public class RedstoneWireTurbo { j = getMaxCurrentStrength(upd, j); int l = 0; @@ -973,18 +940,46 @@ index 9f17170179cc99d84ad25a1e838aff3d8cc66f93..780c31121ea62d986fe6918c095f6179 // The variable 'k' holds the maximum redstone power value of any adjacent blocks. // If 'k' has the highest level of all neighbors, then the power level of this diff --git a/src/main/java/io/papermc/paper/SparksFly.java b/src/main/java/io/papermc/paper/SparksFly.java -index 2955b7ec9832a5752ea4aff9fc9d34ae2f9ee83e..19c4aa20617f555d02f9c1c5a93b7204ab7251d8 100644 +index 62e2d5704c348955bc8284dc2d54c933b7bcdd06..2ad5b9b0b7e18780ee73310451d9fa73f44c4bdb 100644 --- a/src/main/java/io/papermc/paper/SparksFly.java +++ b/src/main/java/io/papermc/paper/SparksFly.java -@@ -47,7 +47,7 @@ public final class SparksFly { +@@ -33,13 +33,13 @@ public final class SparksFly { + + private final Logger logger; + private final PaperSparkModule spark; +- private final ConcurrentLinkedQueue mainThreadTaskQueue; ++ // Folia - region threading + + private boolean enabled; + private boolean disabledInConfigurationWarningLogged; + + public SparksFly(final Server server) { +- this.mainThreadTaskQueue = new ConcurrentLinkedQueue<>(); ++ // Folia - region threading + this.logger = Logger.getLogger(ID); + this.logger.log(Level.INFO, "This server bundles the spark profiler. For more information please visit https://docs.papermc.io/paper/profiling"); + this.spark = PaperSparkModule.create(Compatibility.VERSION_1_0, server, this.logger, new PaperScheduler() { +@@ -50,7 +50,7 @@ public final class SparksFly { @Override public void executeSync(final Runnable runnable) { -- MCUtil.ensureMain(this.catching(runnable, "synchronous")); +- SparksFly.this.mainThreadTaskQueue.offer(this.catching(runnable, "synchronous")); + io.papermc.paper.threadedregions.RegionizedServer.getInstance().addTask(this.catching(runnable, "synchronous")); // Folia - region threading } private Runnable catching(final Runnable runnable, final String type) { +@@ -88,10 +88,7 @@ public final class SparksFly { + } + + public void executeMainThreadTasks() { +- Runnable task; +- while ((task = this.mainThreadTaskQueue.poll()) != null) { +- task.run(); +- } ++ throw new UnsupportedOperationException(); // Folia - region threading + } + + public void enableEarlyIfRequested() { diff --git a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java b/src/main/java/io/papermc/paper/adventure/ChatProcessor.java index 14e412ebf75b0e06ab53a1c8f9dd1be6ad1e2680..3f733319482fedcf7461f4b7466e84afeae1fc2b 100644 --- a/src/main/java/io/papermc/paper/adventure/ChatProcessor.java @@ -1079,7 +1074,7 @@ index 7b58b2d6297800c2dcdbf7539e5ab8e7703f39f1..a587d83b78af4efc484f939529acf708 public static void registerCommands(final MinecraftServer server) { diff --git a/src/main/java/io/papermc/paper/command/subcommands/EntityCommand.java b/src/main/java/io/papermc/paper/command/subcommands/EntityCommand.java -index 777b789fdcdf297309cfb36fc7f77e3fdb6327ca..b5ded5d0ee80e4fc374d873facba5f20e7155e77 100644 +index f671b74e4179fc29bc600b52e456ba9f78d8bbd6..fa3367c7f2b3d509886b152d892fe2168d83c6ae 100644 --- a/src/main/java/io/papermc/paper/command/subcommands/EntityCommand.java +++ b/src/main/java/io/papermc/paper/command/subcommands/EntityCommand.java @@ -129,7 +129,7 @@ public final class EntityCommand implements PaperSubcommand { @@ -1120,10 +1115,10 @@ index bd68139ae635f2ad7ec8e7a21e0056a139c4c62e..48a43341b17247355a531164019d5cc9 } diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -index a9dd0e5216e95afd98fd2200d110e2cc0b1b0dca..a7757603bef0686b3f0debe4a94602f27373534f 100644 +index 9221ce36355eaf8d4456209c57b68486d587c255..60284e762b7f35fb9e1134542b9fd70b06b762ed 100644 --- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -@@ -364,4 +364,18 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -356,4 +356,18 @@ public class GlobalConfiguration extends ConfigurationPart { public boolean disableChorusPlantUpdates = false; public boolean disableMushroomBlockUpdates = false; } @@ -1143,10 +1138,10 @@ index a9dd0e5216e95afd98fd2200d110e2cc0b1b0dca..a7757603bef0686b3f0debe4a94602f2 + // Folia end - threaded regions } diff --git a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java -index fd3b1c10695634f65c7291016bf671c084bc4d57..412f75af328c65eaccd52570915289d6d411b6fd 100644 +index b1c917d65076a3805e5b78cb946753f0c101e214..ad3d9251e88ce9a35b0f46e9f0f54e62559bd9f9 100644 --- a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java +++ b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java -@@ -497,6 +497,14 @@ public class WorldConfiguration extends ConfigurationPart { +@@ -505,6 +505,14 @@ public class WorldConfiguration extends ConfigurationPart { public Chunks chunks; public class Chunks extends ConfigurationPart { @@ -1200,7 +1195,7 @@ index c03608fec96b51e1867f43d8f42e5aefb1520e46..127d96280cad2d4e5db574a089d67ad6 * on all currently scheduled tasks. diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java b/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java new file mode 100644 -index 0000000000000000000000000000000000000000..d1cd3c1428de206d1d0b58e507d5d5a72f846acc +index 0000000000000000000000000000000000000000..e8550cd33ca171aeffb1f40854f80c7ad6c81edf --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java @@ -0,0 +1,174 @@ @@ -1256,7 +1251,7 @@ index 0000000000000000000000000000000000000000..d1cd3c1428de206d1d0b58e507d5d5a7 + + private void saveLevelData(final ServerLevel world) { + try { -+ world.saveLevelData(false); ++ world.saveLevelData(true); + } catch (final Throwable thr) { + LOGGER.error("Failed to save level data for " + world.getWorld().getName(), thr); + } @@ -1621,7 +1616,7 @@ index 0000000000000000000000000000000000000000..1f48ada99d6d24880f9bda1cd05d41a4 +} diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java b/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java new file mode 100644 -index 0000000000000000000000000000000000000000..1d41a6a204068122daa1b5b2cd7541bfeae52f4c +index 0000000000000000000000000000000000000000..fc053ded0c14b76a1c6c82b59d3fd320372a3293 --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java @@ -0,0 +1,455 @@ @@ -2069,7 +2064,7 @@ index 0000000000000000000000000000000000000000..1d41a6a204068122daa1b5b2cd7541bf + + private void tickTime(final ServerLevel world, final int tickCount) { + if (world.tickTime) { -+ if (world.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { ++ if (world.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + world.setDayTime(world.levelData.getDayTime() + (long)tickCount); + } + world.serverLevelData.setGameTime(world.serverLevelData.getGameTime() + (long)tickCount); @@ -2082,16 +2077,17 @@ index 0000000000000000000000000000000000000000..1d41a6a204068122daa1b5b2cd7541bf +} diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionizedTaskQueue.java b/src/main/java/io/papermc/paper/threadedregions/RegionizedTaskQueue.java new file mode 100644 -index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66ddba133f +index 0000000000000000000000000000000000000000..3de00bffe9b54f38e7c8ce30ba738983d0c65eba --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/RegionizedTaskQueue.java -@@ -0,0 +1,763 @@ +@@ -0,0 +1,803 @@ +package io.papermc.paper.threadedregions; + +import ca.spottedleaf.concurrentutil.collection.MultiThreadedQueue; -+import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor; ++import ca.spottedleaf.concurrentutil.executor.PrioritisedExecutor; +import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable; +import ca.spottedleaf.concurrentutil.util.ConcurrentUtil; ++import ca.spottedleaf.concurrentutil.util.Priority; +import ca.spottedleaf.moonrise.common.util.CoordinateUtils; +import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager; +import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; @@ -2111,45 +2107,49 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + + public PrioritisedExecutor.PrioritisedTask createChunkTask(final ServerLevel world, final int chunkX, final int chunkZ, + final Runnable run) { -+ return new PrioritisedQueue.ChunkBasedPriorityTask(world.taskQueueRegionData, chunkX, chunkZ, true, run, PrioritisedExecutor.Priority.NORMAL); ++ return this.createChunkTask(world, chunkX, chunkZ, run, Priority.NORMAL); + } + + public PrioritisedExecutor.PrioritisedTask createChunkTask(final ServerLevel world, final int chunkX, final int chunkZ, -+ final Runnable run, final PrioritisedExecutor.Priority priority) { ++ final Runnable run, final Priority priority) { + return new PrioritisedQueue.ChunkBasedPriorityTask(world.taskQueueRegionData, chunkX, chunkZ, true, run, priority); + } + + public PrioritisedExecutor.PrioritisedTask createTickTaskQueue(final ServerLevel world, final int chunkX, final int chunkZ, + final Runnable run) { -+ return new PrioritisedQueue.ChunkBasedPriorityTask(world.taskQueueRegionData, chunkX, chunkZ, false, run, PrioritisedExecutor.Priority.NORMAL); ++ return this.createTickTaskQueue(world, chunkX, chunkZ, run, Priority.NORMAL); + } + + public PrioritisedExecutor.PrioritisedTask createTickTaskQueue(final ServerLevel world, final int chunkX, final int chunkZ, -+ final Runnable run, final PrioritisedExecutor.Priority priority) { ++ final Runnable run, final Priority priority) { + return new PrioritisedQueue.ChunkBasedPriorityTask(world.taskQueueRegionData, chunkX, chunkZ, false, run, priority); + } + + public PrioritisedExecutor.PrioritisedTask queueChunkTask(final ServerLevel world, final int chunkX, final int chunkZ, + final Runnable run) { -+ return this.queueChunkTask(world, chunkX, chunkZ, run, PrioritisedExecutor.Priority.NORMAL); ++ return this.queueChunkTask(world, chunkX, chunkZ, run, Priority.NORMAL); + } + + public PrioritisedExecutor.PrioritisedTask queueChunkTask(final ServerLevel world, final int chunkX, final int chunkZ, -+ final Runnable run, final PrioritisedExecutor.Priority priority) { ++ final Runnable run, final Priority priority) { + final PrioritisedExecutor.PrioritisedTask ret = this.createChunkTask(world, chunkX, chunkZ, run, priority); ++ + ret.queue(); ++ + return ret; + } + + public PrioritisedExecutor.PrioritisedTask queueTickTaskQueue(final ServerLevel world, final int chunkX, final int chunkZ, + final Runnable run) { -+ return this.queueTickTaskQueue(world, chunkX, chunkZ, run, PrioritisedExecutor.Priority.NORMAL); ++ return this.queueTickTaskQueue(world, chunkX, chunkZ, run, Priority.NORMAL); + } + + public PrioritisedExecutor.PrioritisedTask queueTickTaskQueue(final ServerLevel world, final int chunkX, final int chunkZ, -+ final Runnable run, final PrioritisedExecutor.Priority priority) { ++ final Runnable run, final Priority priority) { + final PrioritisedExecutor.PrioritisedTask ret = this.createTickTaskQueue(world, chunkX, chunkZ, run, priority); ++ + ret.queue(); ++ + return ret; + } + @@ -2360,8 +2360,8 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + } + + static final class PrioritisedQueue { -+ private final ArrayDeque[] queues = new ArrayDeque[PrioritisedExecutor.Priority.TOTAL_SCHEDULABLE_PRIORITIES]; { -+ for (int i = 0; i < PrioritisedExecutor.Priority.TOTAL_SCHEDULABLE_PRIORITIES; ++i) { ++ private final ArrayDeque[] queues = new ArrayDeque[Priority.TOTAL_SCHEDULABLE_PRIORITIES]; { ++ for (int i = 0; i < Priority.TOTAL_SCHEDULABLE_PRIORITIES; ++i) { + this.queues[i] = new ArrayDeque<>(); + } + } @@ -2381,7 +2381,7 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + + public boolean isEmpty() { + final ArrayDeque[] queues = this.queues; -+ final int max = PrioritisedExecutor.Priority.IDLE.priority; ++ final int max = Priority.IDLE.priority; + synchronized (this) { + for (int i = 0; i <= max; ++i) { + if (!queues[i].isEmpty()) { @@ -2446,7 +2446,7 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + } + + split.computeIfAbsent(region, (keyInMap) -> { -+ final ArrayDeque[] ret = new ArrayDeque[PrioritisedExecutor.Priority.TOTAL_SCHEDULABLE_PRIORITIES]; ++ final ArrayDeque[] ret = new ArrayDeque[Priority.TOTAL_SCHEDULABLE_PRIORITIES]; + + for (int k = 0; k < ret.length; ++k) { + ret[k] = new ArrayDeque<>(); @@ -2476,8 +2476,8 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + private Boolean tryPush(final ChunkBasedPriorityTask task) { + final ArrayDeque[] queues = this.queues; + synchronized (this) { -+ final PrioritisedExecutor.Priority priority = task.getPriority(); -+ if (priority == PrioritisedExecutor.Priority.COMPLETING) { ++ final Priority priority = task.getPriority(); ++ if (priority == Priority.COMPLETING) { + return null; + } + if (this.isDestroyed) { @@ -2490,7 +2490,7 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + + private boolean executeTask() { + final ArrayDeque[] queues = this.queues; -+ final int max = PrioritisedExecutor.Priority.IDLE.priority; ++ final int max = Priority.IDLE.priority; + ChunkBasedPriorityTask task = null; + AtomicLong referenceCounter = null; + synchronized (this) { @@ -2535,11 +2535,11 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + private volatile AtomicLong referenceCounter; + private static final VarHandle REFERENCE_COUNTER_HANDLE = ConcurrentUtil.getVarHandle(ChunkBasedPriorityTask.class, "referenceCounter", AtomicLong.class); + private Runnable run; -+ private volatile PrioritisedExecutor.Priority priority; -+ private static final VarHandle PRIORITY_HANDLE = ConcurrentUtil.getVarHandle(ChunkBasedPriorityTask.class, "priority", PrioritisedExecutor.Priority.class); ++ private volatile Priority priority; ++ private static final VarHandle PRIORITY_HANDLE = ConcurrentUtil.getVarHandle(ChunkBasedPriorityTask.class, "priority", Priority.class); + + ChunkBasedPriorityTask(final WorldRegionTaskData world, final int chunkX, final int chunkZ, final boolean isChunkTask, -+ final Runnable run, final PrioritisedExecutor.Priority priority) { ++ final Runnable run, final Priority priority) { + this.world = world; + this.chunkX = chunkX; + this.chunkZ = chunkZ; @@ -2554,20 +2554,20 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + this.sectionLowerLeftCoord = CoordinateUtils.getChunkKey(chunkX & ~regionMask, chunkZ & ~regionMask); + } + -+ private PrioritisedExecutor.Priority getPriorityVolatile() { -+ return (PrioritisedExecutor.Priority)PRIORITY_HANDLE.getVolatile(this); ++ private Priority getPriorityVolatile() { ++ return (Priority)PRIORITY_HANDLE.getVolatile(this); + } + -+ private void setPriorityPlain(final PrioritisedExecutor.Priority priority) { ++ private void setPriorityPlain(final Priority priority) { + PRIORITY_HANDLE.set(this, priority); + } + -+ private void setPriorityVolatile(final PrioritisedExecutor.Priority priority) { ++ private void setPriorityVolatile(final Priority priority) { + PRIORITY_HANDLE.setVolatile(this, priority); + } + -+ private PrioritisedExecutor.Priority compareAndExchangePriority(final PrioritisedExecutor.Priority expect, final PrioritisedExecutor.Priority update) { -+ return (PrioritisedExecutor.Priority)PRIORITY_HANDLE.compareAndExchange(this, expect, update); ++ private Priority compareAndExchangePriority(final Priority expect, final Priority update) { ++ return (Priority)PRIORITY_HANDLE.compareAndExchange(this, expect, update); + } + + private void setReferenceCounterPlain(final AtomicLong value) { @@ -2611,7 +2611,7 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + } + + // we have the reference count, we win no matter what. -+ this.setPriorityVolatile(PrioritisedExecutor.Priority.COMPLETING); ++ this.setPriorityVolatile(Priority.COMPLETING); + + try { + if (cancel) { @@ -2630,6 +2630,16 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + } + + @Override ++ public PrioritisedExecutor getExecutor() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public boolean isQueued() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override + public boolean queue() { + if (this.getReferenceCounterVolatile() != REFERENCE_COUNTER_NOT_SET) { + return false; @@ -2687,12 +2697,12 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + + private AtomicLong trySetCompleting(final int minPriority) { + // first, try to set priority to EXECUTING -+ for (PrioritisedExecutor.Priority curr = this.getPriorityVolatile();;) { ++ for (Priority curr = this.getPriorityVolatile();;) { + if (curr.isLowerPriority(minPriority)) { + return null; + } + -+ if (curr == (curr = this.compareAndExchangePriority(curr, PrioritisedExecutor.Priority.COMPLETING))) { ++ if (curr == (curr = this.compareAndExchangePriority(curr, Priority.COMPLETING))) { + break; + } // else: continue + } @@ -2723,7 +2733,7 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + return; + } + -+ if (this.getPriorityVolatile() == PrioritisedExecutor.Priority.COMPLETING) { ++ if (this.getPriorityVolatile() == Priority.COMPLETING) { + // cancelled + return; + } @@ -2761,15 +2771,15 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + } + + @Override -+ public PrioritisedExecutor.Priority getPriority() { ++ public Priority getPriority() { + return this.getPriorityVolatile(); + } + + @Override -+ public boolean lowerPriority(final PrioritisedExecutor.Priority priority) { ++ public boolean lowerPriority(final Priority priority) { + int failures = 0; -+ for (PrioritisedExecutor.Priority curr = this.getPriorityVolatile();;) { -+ if (curr == PrioritisedExecutor.Priority.COMPLETING) { ++ for (Priority curr = this.getPriorityVolatile();;) { ++ if (curr == Priority.COMPLETING) { + return false; + } + @@ -2790,10 +2800,35 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + } + + @Override -+ public boolean setPriority(final PrioritisedExecutor.Priority priority) { ++ public long getSubOrder() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public boolean setSubOrder(final long subOrder) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public boolean raiseSubOrder(final long subOrder) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public boolean lowerSubOrder(final long subOrder) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public boolean setPriorityAndSubOrder(final Priority priority, final long subOrder) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public boolean setPriority(final Priority priority) { + int failures = 0; -+ for (PrioritisedExecutor.Priority curr = this.getPriorityVolatile();;) { -+ if (curr == PrioritisedExecutor.Priority.COMPLETING) { ++ for (Priority curr = this.getPriorityVolatile();;) { ++ if (curr == Priority.COMPLETING) { + return false; + } + @@ -2814,10 +2849,10 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 + } + + @Override -+ public boolean raisePriority(final PrioritisedExecutor.Priority priority) { ++ public boolean raisePriority(final Priority priority) { + int failures = 0; -+ for (PrioritisedExecutor.Priority curr = this.getPriorityVolatile();;) { -+ if (curr == PrioritisedExecutor.Priority.COMPLETING) { ++ for (Priority curr = this.getPriorityVolatile();;) { ++ if (curr == Priority.COMPLETING) { + return false; + } + @@ -2851,10 +2886,10 @@ index 0000000000000000000000000000000000000000..a1e1782d87403ca8934d37361be7ba66 +} diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java b/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java new file mode 100644 -index 0000000000000000000000000000000000000000..cd89a11ff94dfbb9c9e259b85f931bd0d160c06e +index 0000000000000000000000000000000000000000..1b741d4bccfd45beeec43300f44770516c0d850e --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/RegionizedWorldData.java -@@ -0,0 +1,751 @@ +@@ -0,0 +1,770 @@ +package io.papermc.paper.threadedregions; + +import ca.spottedleaf.moonrise.common.list.IteratorSafeOrderedReferenceSet; @@ -2867,6 +2902,7 @@ index 0000000000000000000000000000000000000000..cd89a11ff94dfbb9c9e259b85f931bd0 +import it.unimi.dsi.fastutil.longs.Long2ReferenceMap; +import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; ++import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet; +import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; +import net.minecraft.CrashReport; +import net.minecraft.ReportedException; @@ -2877,6 +2913,7 @@ index 0000000000000000000000000000000000000000..cd89a11ff94dfbb9c9e259b85f931bd0 +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.protocol.common.ClientboundDisconnectPacket; +import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; @@ -2891,6 +2928,7 @@ index 0000000000000000000000000000000000000000..cd89a11ff94dfbb9c9e259b85f931bd0 +import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.NaturalSpawner; ++import net.minecraft.world.level.ServerExplosion; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.RedStoneWireBlock; @@ -2914,6 +2952,7 @@ index 0000000000000000000000000000000000000000..cd89a11ff94dfbb9c9e259b85f931bd0 +import java.util.Iterator; +import java.util.List; +import java.util.Map; ++import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Predicate; + @@ -3007,6 +3046,10 @@ index 0000000000000000000000000000000000000000..cd89a11ff94dfbb9c9e259b85f931bd0 + into.wanderingTraderSpawnDelay = Math.max(from.wanderingTraderSpawnDelay, into.wanderingTraderSpawnDelay); + into.wanderingTraderSpawnChance = Math.max(from.wanderingTraderSpawnChance, into.wanderingTraderSpawnChance); + } ++ // chunkHoldersToBroadcast ++ for (final ChunkHolder chunkHolder : from.chunkHoldersToBroadcast) { ++ into.chunkHoldersToBroadcast.add(chunkHolder); ++ } + } + + @Override @@ -3163,6 +3206,16 @@ index 0000000000000000000000000000000000000000..cd89a11ff94dfbb9c9e259b85f931bd0 + regionizedWorldData.wanderingTraderSpawnDelay = from.wanderingTraderSpawnDelay; + regionizedWorldData.villageSiegeState = new VillageSiegeState(); // just re set it, as the spawn pos will be invalid + } ++ // chunkHoldersToBroadcast ++ for (final ChunkHolder chunkHolder : from.chunkHoldersToBroadcast) { ++ final ChunkPos pos = chunkHolder.getPos(); ++ ++ // Possible for get() to return null, as the chunk holder is not removed during unload ++ final RegionizedWorldData into = regionToData.get(CoordinateUtils.getChunkKey(pos.x >> chunkToRegionShift, pos.z >> chunkToRegionShift)); ++ if (into != null) { ++ into.chunkHoldersToBroadcast.add(chunkHolder); ++ } ++ } + } + }; + @@ -3254,9 +3307,10 @@ index 0000000000000000000000000000000000000000..cd89a11ff94dfbb9c9e259b85f931bd0 + @VisibleForDebug + public NaturalSpawner.SpawnState lastSpawnState; + public boolean shouldSignal = true; -+ public final Map explosionDensityCache = new HashMap<>(64, 0.25f); ++ public final Map explosionDensityCache = new HashMap<>(64, 0.25f); + public final PathTypeCache pathTypesByPosCache = new PathTypeCache(); -+ public ServerChunkCache.ChunkAndHolder[] iterationCopy; // Paper - chunk tick iteration optimisations ++ public final List temporaryChunkTickList = new java.util.ArrayList<>(); ++ public final Set chunkHoldersToBroadcast = new ReferenceLinkedOpenHashSet<>(); + + // not transient + public java.util.ArrayDeque redstoneUpdateInfos; @@ -3286,8 +3340,8 @@ index 0000000000000000000000000000000000000000..cd89a11ff94dfbb9c9e259b85f931bd0 + + public RegionizedWorldData(final ServerLevel world) { + this.world = world; -+ this.blockLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world.getProfilerSupplier(), world, true); -+ this.fluidLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world.getProfilerSupplier(), world, false); ++ this.blockLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, true); ++ this.fluidLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, false); + this.neighborUpdater = new CollectingNeighborUpdater(world, world.neighbourUpdateMax); + this.nearbyPlayers = new NearbyPlayers(world); + this.wireHandler = new alternate.current.wire.WireHandler(world); @@ -3705,13 +3759,13 @@ index 0000000000000000000000000000000000000000..112d24a93bddf3d81c9176c05340c94e +} diff --git a/src/main/java/io/papermc/paper/threadedregions/TeleportUtils.java b/src/main/java/io/papermc/paper/threadedregions/TeleportUtils.java new file mode 100644 -index 0000000000000000000000000000000000000000..7b31c4ea6d01f936271bdadc3626201dcf32a683 +index 0000000000000000000000000000000000000000..74ac328bf8d5f762f7060a6c5d49089dee1ddaea --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/TeleportUtils.java @@ -0,0 +1,70 @@ +package io.papermc.paper.threadedregions; + -+import ca.spottedleaf.concurrentutil.completable.Completable; ++import ca.spottedleaf.concurrentutil.completable.CallbackCompletable; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import org.bukkit.Location; @@ -3724,7 +3778,7 @@ index 0000000000000000000000000000000000000000..7b31c4ea6d01f936271bdadc3626201d + public static void teleport(final Entity from, final boolean useFromRootVehicle, final Entity to, final Float yaw, final Float pitch, + final long teleportFlags, final PlayerTeleportEvent.TeleportCause cause, final Consumer onComplete) { + // retrieve coordinates -+ final Completable positionCompletable = new Completable<>(); ++ final CallbackCompletable positionCompletable = new CallbackCompletable<>(); + + positionCompletable.addWaiter( + (final Location loc, final Throwable thr) -> { @@ -7435,11 +7489,175 @@ index 0000000000000000000000000000000000000000..85d3965a67cfb59790c664baa7840b50 + } + } +} +diff --git a/src/main/java/io/papermc/paper/threadedregions/util/SimpleThreadLocalRandomSource.java b/src/main/java/io/papermc/paper/threadedregions/util/SimpleThreadLocalRandomSource.java +new file mode 100644 +index 0000000000000000000000000000000000000000..97cd0e767ed36eeb211ecdf125e8d2bfff19a15e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/threadedregions/util/SimpleThreadLocalRandomSource.java +@@ -0,0 +1,79 @@ ++package io.papermc.paper.threadedregions.util; ++ ++import net.minecraft.util.RandomSource; ++import net.minecraft.world.level.levelgen.BitRandomSource; ++import net.minecraft.world.level.levelgen.PositionalRandomFactory; ++import java.util.concurrent.ThreadLocalRandom; ++ ++public final class SimpleThreadLocalRandomSource implements BitRandomSource { ++ ++ public static final SimpleThreadLocalRandomSource INSTANCE = new SimpleThreadLocalRandomSource(); ++ ++ private final PositionalRandomFactory positionalRandomFactory = new SimpleThreadLocalRandomSource.SimpleThreadLocalRandomPositionalRandomFactory(); ++ ++ private SimpleThreadLocalRandomSource() {} ++ ++ @Override ++ public int next(final int bits) { ++ return ThreadLocalRandom.current().nextInt() >>> (Integer.SIZE - bits); ++ } ++ ++ @Override ++ public int nextInt() { ++ return ThreadLocalRandom.current().nextInt(); ++ } ++ ++ @Override ++ public int nextInt(final int bound) { ++ if (bound <= 0) { ++ throw new IllegalArgumentException(); ++ } ++ ++ // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ ++ final long value = (long)this.nextInt() & 0xFFFFFFFFL; ++ return (int)((value * (long)bound) >>> Integer.SIZE); ++ } ++ ++ @Override ++ public void setSeed(final long seed) { ++ // no-op ++ } ++ ++ @Override ++ public double nextGaussian() { ++ return ThreadLocalRandom.current().nextGaussian(); ++ } ++ ++ @Override ++ public RandomSource fork() { ++ return this; ++ } ++ ++ @Override ++ public PositionalRandomFactory forkPositional() { ++ return this.positionalRandomFactory; ++ } ++ ++ private static final class SimpleThreadLocalRandomPositionalRandomFactory implements PositionalRandomFactory { ++ ++ @Override ++ public RandomSource fromHashOf(final String seed) { ++ return SimpleThreadLocalRandomSource.INSTANCE; ++ } ++ ++ @Override ++ public RandomSource fromSeed(final long seed) { ++ return SimpleThreadLocalRandomSource.INSTANCE; ++ } ++ ++ @Override ++ public RandomSource at(final int x, final int y, final int z) { ++ return SimpleThreadLocalRandomSource.INSTANCE; ++ } ++ ++ @Override ++ public void parityConfigString(final StringBuilder info) { ++ info.append("SimpleThreadLocalRandomPositionalRandomFactory{}"); ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/threadedregions/util/ThreadLocalRandomSource.java b/src/main/java/io/papermc/paper/threadedregions/util/ThreadLocalRandomSource.java +new file mode 100644 +index 0000000000000000000000000000000000000000..eda02661b1c09e5303d3912c2562bb1c4ccc04fe +--- /dev/null ++++ b/src/main/java/io/papermc/paper/threadedregions/util/ThreadLocalRandomSource.java +@@ -0,0 +1,73 @@ ++package io.papermc.paper.threadedregions.util; ++ ++import net.minecraft.util.RandomSource; ++import net.minecraft.world.level.levelgen.BitRandomSource; ++import net.minecraft.world.level.levelgen.PositionalRandomFactory; ++import java.util.concurrent.ThreadLocalRandom; ++ ++public final class ThreadLocalRandomSource implements BitRandomSource { ++ ++ public static final ThreadLocalRandomSource INSTANCE = new ThreadLocalRandomSource(); ++ ++ private final PositionalRandomFactory positionalRandomFactory = new ThreadLocalRandomPositionalRandomFactory(); ++ ++ private ThreadLocalRandomSource() {} ++ ++ @Override ++ public int next(final int bits) { ++ return ThreadLocalRandom.current().nextInt() >>> (Integer.SIZE - bits); ++ } ++ ++ @Override ++ public int nextInt() { ++ return ThreadLocalRandom.current().nextInt(); ++ } ++ ++ @Override ++ public int nextInt(final int bound) { ++ return ThreadLocalRandom.current().nextInt(bound); ++ } ++ ++ @Override ++ public void setSeed(final long seed) { ++ // no-op ++ } ++ ++ @Override ++ public double nextGaussian() { ++ return ThreadLocalRandom.current().nextGaussian(); ++ } ++ ++ @Override ++ public RandomSource fork() { ++ return this; ++ } ++ ++ @Override ++ public PositionalRandomFactory forkPositional() { ++ return this.positionalRandomFactory; ++ } ++ ++ private static final class ThreadLocalRandomPositionalRandomFactory implements PositionalRandomFactory { ++ ++ @Override ++ public RandomSource fromHashOf(final String seed) { ++ return ThreadLocalRandomSource.INSTANCE; ++ } ++ ++ @Override ++ public RandomSource fromSeed(final long seed) { ++ return ThreadLocalRandomSource.INSTANCE; ++ } ++ ++ @Override ++ public RandomSource at(final int x, final int y, final int z) { ++ return ThreadLocalRandomSource.INSTANCE; ++ } ++ ++ @Override ++ public void parityConfigString(final StringBuilder info) { ++ info.append("ThreadLocalRandomPositionalRandomFactory{}"); ++ } ++ } ++} diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java -index 0449d4619e3a0752dea0981fb149542e23076c52..5931afeccc17733103641c9d84390617fc9f62c0 100644 +index 9d97c9afa31bed6d2e6b7778bfe4cc41cea31c4d..d81a543206f808b7a36204dd277391370186ea43 100644 --- a/src/main/java/io/papermc/paper/util/MCUtil.java +++ b/src/main/java/io/papermc/paper/util/MCUtil.java -@@ -90,6 +90,7 @@ public final class MCUtil { +@@ -98,6 +98,7 @@ public final class MCUtil { */ public static void ensureMain(String reason, Runnable run) { if (!isMainThread()) { @@ -7447,7 +7665,7 @@ index 0449d4619e3a0752dea0981fb149542e23076c52..5931afeccc17733103641c9d84390617 if (reason != null) { MinecraftServer.LOGGER.warn("Asynchronous " + reason + "!", new IllegalStateException()); } -@@ -144,6 +145,30 @@ public final class MCUtil { +@@ -152,6 +153,30 @@ public final class MCUtil { return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ()); } @@ -7479,10 +7697,10 @@ index 0449d4619e3a0752dea0981fb149542e23076c52..5931afeccc17733103641c9d84390617 return new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); } diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java -index 2d344df35d47b4b1ecddf32ccaa4dae41e5f58cb..8263a1134582675e67afd5ee07c6d3d06172c460 100644 +index 13bd145b1e8006a53c22f5dc0c78f29b540c7663..6d87797523337725141f271087f80065ed67347e 100644 --- a/src/main/java/net/minecraft/commands/CommandSourceStack.java +++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java -@@ -67,7 +67,7 @@ public class CommandSourceStack implements ExecutionCommandSource(player.getBukkitEntity(), (RootCommandNode) rootcommandnode, false).callEvent(); // Paper - Brigadier API @@ -7604,20 +7824,20 @@ index 5af48400f87500166dd889c57a8df0aadb08d43d..442a5b557e5867038fcddf597951584f private void runSync(ServerPlayer player, Collection bukkit, RootCommandNode rootcommandnode) { diff --git a/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java -index 6df0db8b4cdab23494ea34236949ece4989110a3..2fd670d941bd575f99def28732ffee29f37a3182 100644 +index ddb264443f2e38b6348226016f9139727c588898..b8c3d6aa9356beeb4bfb431e8d2dd7367969dd8d 100644 --- a/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java -@@ -63,7 +63,7 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior { +@@ -54,7 +54,7 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d1, d2 + d4, d3)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } diff --git a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java -index 39c96f5db6e90a470404c6387fa0c1d5531822e5..526a24d30e193a9f6760e9392364360f6f5fe020 100644 +index 8aae1d113e84dfad9f2b6f0bcd203ca6c68bc5ce..ca98699f4225192bb3364397402b07001b1402af 100644 --- a/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/DefaultDispenseItemBehavior.java @@ -87,7 +87,7 @@ public class DefaultDispenseItemBehavior implements DispenseItemBehavior { @@ -7625,96 +7845,87 @@ index 39c96f5db6e90a470404c6387fa0c1d5531822e5..526a24d30e193a9f6760e9392364360f BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), CraftVector.toBukkit(entityitem.getDeltaMovement())); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading world.getCraftServer().getPluginManager().callEvent(event); } diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -index 60d3319016beb4f60cbc26dde165f64cf7577602..f2fe380c0cd07afabfaa257d5db04c4064f7a3cb 100644 +index 0d12605dc84dad49faa18bf1fd058c3c168623ee..fa673b087eea4b48edf3c9ac48720fafc8d6f6ba 100644 --- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java -@@ -115,7 +115,7 @@ public interface DispenseItemBehavior { +@@ -111,7 +111,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -174,7 +174,7 @@ public interface DispenseItemBehavior { +@@ -170,7 +170,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -229,7 +229,7 @@ public interface DispenseItemBehavior { +@@ -225,7 +225,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity()); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading world.getCraftServer().getPluginManager().callEvent(event); } -@@ -285,7 +285,7 @@ public interface DispenseItemBehavior { - CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); - - BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorseabstract.getBukkitEntity()); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading - world.getCraftServer().getPluginManager().callEvent(event); - } - -@@ -359,7 +359,7 @@ public interface DispenseItemBehavior { +@@ -280,7 +280,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityhorsechestedabstract.getBukkitEntity()); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading world.getCraftServer().getPluginManager().callEvent(event); } -@@ -431,7 +431,7 @@ public interface DispenseItemBehavior { +@@ -354,7 +354,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -496,7 +496,7 @@ public interface DispenseItemBehavior { +@@ -419,7 +419,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -534,7 +534,7 @@ public interface DispenseItemBehavior { +@@ -457,7 +457,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); // Paper - ignore stack size on damageable items BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -596,7 +596,7 @@ public interface DispenseItemBehavior { +@@ -519,7 +519,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -614,7 +614,8 @@ public interface DispenseItemBehavior { +@@ -537,7 +537,8 @@ public interface DispenseItemBehavior { } } @@ -7724,7 +7935,7 @@ index 60d3319016beb4f60cbc26dde165f64cf7577602..f2fe380c0cd07afabfaa257d5db04c40 // CraftBukkit end if (!BoneMealItem.growCrop(stack, worldserver, blockposition) && !BoneMealItem.growWaterPlant(stack, worldserver, blockposition, (Direction) null)) { -@@ -623,13 +624,13 @@ public interface DispenseItemBehavior { +@@ -546,13 +547,13 @@ public interface DispenseItemBehavior { worldserver.levelEvent(1505, blockposition, 15); } // CraftBukkit start @@ -7744,66 +7955,92 @@ index 60d3319016beb4f60cbc26dde165f64cf7577602..f2fe380c0cd07afabfaa257d5db04c40 StructureGrowEvent structureEvent = null; if (treeType != null) { structureEvent = new StructureGrowEvent(location, treeType, false, null, blocks); -@@ -665,7 +666,7 @@ public interface DispenseItemBehavior { +@@ -588,7 +589,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -722,7 +723,7 @@ public interface DispenseItemBehavior { +@@ -631,7 +632,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -771,7 +772,7 @@ public interface DispenseItemBehavior { +@@ -680,7 +681,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -833,7 +834,7 @@ public interface DispenseItemBehavior { +@@ -742,7 +743,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - only single item in event BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -915,7 +916,7 @@ public interface DispenseItemBehavior { - CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); +@@ -824,7 +825,7 @@ public interface DispenseItemBehavior { + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); // Paper - ignore stack size on damageable items BlockDispenseEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) list.get(0).getBukkitEntity()); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading world.getCraftServer().getPluginManager().callEvent(event); } +diff --git a/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java +index bf8c511739265c6a9cd277752e844481598f8966..c369c0cad19ade00a1e62e834568f1049fb021cd 100644 +--- a/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/EquipmentDispenseItemBehavior.java +@@ -50,7 +50,7 @@ public class EquipmentDispenseItemBehavior extends DefaultDispenseItemBehavior { + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + + BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityliving.getBukkitEntity()); +- if (!DispenserBlock.eventFired) { ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading + world.getCraftServer().getPluginManager().callEvent(event); + } + +diff --git a/src/main/java/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java +index 3588896b7413be73ade6b3f8fd111d02c48ec550..add1e68b3be50ad5f2894fa40182f5448dcf2537 100644 +--- a/src/main/java/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java ++++ b/src/main/java/net/minecraft/core/dispenser/MinecartDispenseItemBehavior.java +@@ -74,7 +74,7 @@ public class MinecartDispenseItemBehavior extends DefaultDispenseItemBehavior { + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + + BlockDispenseEvent event = new BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(vec3d1.x, vec3d1.y, vec3d1.z)); +- if (!DispenserBlock.eventFired) { ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading + worldserver.getCraftServer().getPluginManager().callEvent(event); + } + diff --git a/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java -index e37d2d29f3ba67cfe28abe4847a3dca07121f0be..067f888fdaeced3350c858e2b825a3841b539193 100644 +index 54c72cf472e06e214eb61bd8615a0bb27690c807..f8cb78e6347eb4cb0c5942ae8c75728ed1389970 100644 --- a/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/ProjectileDispenseBehavior.java -@@ -45,7 +45,7 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior { +@@ -43,7 +43,7 @@ public class ProjectileDispenseBehavior extends DefaultDispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ())); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -index 44b79a7c2f8b95a484d1999fa2167ce588f7985b..624df8e8dbf0922c9403d951967312128866515d 100644 +index 65ed3d77a51b8299517e0c165403b0c5ac413475..bb1180f8739bb211c220950d4612eb8e59ee4afe 100644 --- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java @@ -41,7 +41,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { @@ -7811,12 +8048,12 @@ index 44b79a7c2f8b95a484d1999fa2167ce588f7985b..624df8e8dbf0922c9403d95196731212 BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0)); - if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading ++ if (!DispenserBlock.eventFired.get().booleanValue()) { // Folia - region threading worldserver.getCraftServer().getPluginManager().callEvent(event); } diff --git a/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java -index cb308808906a8cdb127df8284e106e00553473ca..05bc1f010b50e673e9a185d96e338baef7ccad03 100644 +index 8f9fde5489c0e1d0a91203536caddec5a9c96f6c..d43489fa1f69f025d44b881205afba39bdebba1c 100644 --- a/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java @@ -37,7 +37,7 @@ public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior { @@ -7829,7 +8066,7 @@ index cb308808906a8cdb127df8284e106e00553473ca..05bc1f010b50e673e9a185d96e338bae } diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 4a8356a714ed50d4a32bcf046a2e16491bef014b..cf160825199374f2c99ac200b371da95c612043c 100644 +index e693a003ea8f022eef8b49e4332025b769333b30..4c3961a10691362657b894a757d201069842d8d7 100644 --- a/src/main/java/net/minecraft/network/Connection.java +++ b/src/main/java/net/minecraft/network/Connection.java @@ -93,7 +93,7 @@ public class Connection extends SimpleChannelInboundHandler> { @@ -8158,7 +8395,7 @@ index 4a8356a714ed50d4a32bcf046a2e16491bef014b..cf160825199374f2c99ac200b371da95 private static class InnerUtil { // Attempt to hide these methods from ProtocolLib, so it doesn't accidently pick them up. diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -index e2c24813f59c2fd075c740ac1842a38f20ed8554..fbc619a132c6ca6b1abab51ac230be29367e9c6e 100644 +index 1f7f68aad97ee73763c042837f239bdc7167db55..d6eb8f495688a1b65a4c419aa3ee655cd8eb322a 100644 --- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java +++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java @@ -46,7 +46,7 @@ public class PacketUtils { @@ -8170,7 +8407,7 @@ index e2c24813f59c2fd075c740ac1842a38f20ed8554..fbc619a132c6ca6b1abab51ac230be29 packetProcessing.push(listener); // Paper - detailed watchdog information try { // Paper - detailed watchdog information if (listener instanceof ServerCommonPacketListenerImpl serverCommonPacketListener && serverCommonPacketListener.processedDisconnect) return; // CraftBukkit - Don't handle sync packets for kicked players -@@ -75,7 +75,23 @@ public class PacketUtils { +@@ -74,7 +74,23 @@ public class PacketUtils { } // Paper end - detailed watchdog information @@ -8196,10 +8433,10 @@ index e2c24813f59c2fd075c740ac1842a38f20ed8554..fbc619a132c6ca6b1abab51ac230be29 } } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 696d075ca2883f3c37e35f983c4d020e5db89d16..84f1f7956065de039837ceeaeee30259a7df4118 100644 +index c26e3a239441376f2694782d4f07943538677c71..ee55c53d40dbf51f47627a6b56060e32fd215353 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -210,7 +210,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; // Paper - don't store the vanilla dispatcher -@@ -323,6 +322,34 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping + // Folia start - regionised ticking + public final io.papermc.paper.threadedregions.RegionizedServer regionizedServer = new io.papermc.paper.threadedregions.RegionizedServer(); + + @Override -+ public void execute(Runnable runnable) { ++ public CompletableFuture submit(java.util.function.Supplier task) { + if (true) { + throw new UnsupportedOperationException(); + } -+ super.execute(runnable); ++ return super.submit(task); ++ } ++ ++ @Override ++ public CompletableFuture submit(Runnable task) { ++ if (true) { ++ throw new UnsupportedOperationException(); ++ } ++ return super.submit(task); ++ } ++ ++ @Override ++ public void schedule(TickTask task) { ++ if (true) { ++ throw new UnsupportedOperationException(); ++ } ++ super.schedule(task); + } + + @Override @@ -8251,18 +8504,18 @@ index 696d075ca2883f3c37e35f983c4d020e5db89d16..84f1f7956065de039837ceeaeee30259 + } + + @Override -+ public void tell(TickTask runnable) { ++ public void execute(Runnable runnable) { + if (true) { + throw new UnsupportedOperationException(); + } -+ super.tell(runnable); ++ super.execute(runnable); + } + // Folia end - regionised ticking + public static S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); Thread thread = new ca.spottedleaf.moonrise.common.util.TickThread(() -> { // Paper - rewrite chunk system -@@ -356,46 +383,30 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 ? Mth.square(ChunkProgressListener.calculateDiameter(i)) : 0; @@ -8399,7 +8652,7 @@ index 696d075ca2883f3c37e35f983c4d020e5db89d16..84f1f7956065de039837ceeaeee30259 // Iterator iterator = this.levels.values().iterator(); if (true) { -@@ -921,7 +944,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -- return false; -- } : this::haveTime); -+ if (true) throw new UnsupportedOperationException(); // Folia - region threading - // Paper start - rewrite chunk system - final Throwable crash = this.chunkSystemCrash; - if (crash != null) { -@@ -1487,21 +1564,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { +- return false; +- } : this::haveTime); ++ if (true) throw new UnsupportedOperationException(); // Folia - region threading + // Paper start - rewrite chunk system + final Throwable crash = this.chunkSystemCrash; + if (crash != null) { +@@ -1529,21 +1622,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { ++ if (false && j > 0) { // Folia - region threading - this is complicated to implement, and even if done correctly is messy + if (this.playerList.getPlayerCount() == 0 && !this.tickRateManager.isSprinting() && this.pluginsBlockingSleep.isEmpty()) { // Paper - API to allow/disallow tick sleeping + ++this.emptyTicks; + } else { +@@ -1650,24 +1743,59 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop true, false); + } + // Paper end - avoid issues with certain tasks not processing during sleep +- this.server.spark.executeMainThreadTasks(); // Paper - spark ++ // Folia - region threading + this.tickConnection(); + this.server.spark.tickEnd(((double)(System.nanoTime() - lastTick) / 1000000D)); // Paper - spark + return; + } + } + ++ // Folia start - region threading + if (region != null) { + region.world.getCurrentWorldData().updateTickData(); + if (region.world.checkInitialised.get() != ServerLevel.WORLD_INIT_CHECKED) { @@ -8607,26 +8885,15 @@ index 696d075ca2883f3c37e35f983c4d020e5db89d16..84f1f7956065de039837ceeaeee30259 + BooleanSupplier shouldKeepTicking = () -> { + return scheduledEnd - System.nanoTime() > targetBuffer; + }; -+ this.server.spark.tickStart(); // Paper - spark -+ new com.destroystokyo.paper.event.server.ServerTickStartEvent((int)region.getCurrentTick()).callEvent(); // Paper + // Folia end - region threading - co.aikar.timings.TimingsManager.FULL_SERVER_TICK.startTiming(); // Paper -- long i = Util.getNanos(); -+ long i = startTime; // Folia - region threading - - // Paper start - move oversleep into full server tick -+ if (region == null) { // Folia - region threading - isOversleep = true;MinecraftTimings.serverOversleep.startTiming(); - this.managedBlock(() -> { - return !this.canOversleep(); - }); - isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -+ } // Folia - region threading - // Paper end -- this.server.spark.tickStart(); // Paper - spark -- new com.destroystokyo.paper.event.server.ServerTickStartEvent(this.tickCount+1).callEvent(); // Paper - Server Tick Events -+ // Folia - region threading - move up + + this.server.spark.tickStart(); // Paper - spark +- new com.destroystokyo.paper.event.server.ServerTickStartEvent(this.tickCount+1).callEvent(); // Paper - Server Tick Events +- ++this.tickCount; +- this.tickRateManager.tick(); +- this.tickChildren(shouldKeepTicking); +- if (i - this.lastServerStatus >= MinecraftServer.STATUS_EXPIRE_TIME_NANOS) { ++ new com.destroystokyo.paper.event.server.ServerTickStartEvent((int)region.getCurrentTick()).callEvent(); // Paper - Server Tick Events // Folia - region threading + // Folia start - region threading + if (region != null) { + region.getTaskQueueData().drainTasks(); @@ -8644,12 +8911,6 @@ index 696d075ca2883f3c37e35f983c4d020e5db89d16..84f1f7956065de039837ceeaeee30259 + } + } + // Folia end - region threading - -- ++this.tickCount; -- this.tickRateManager.tick(); -- this.tickChildren(shouldKeepTicking); -- if (i - this.lastServerStatus >= MinecraftServer.STATUS_EXPIRE_TIME_NANOS) { -+ // Folia - region threading + if (region == null) this.tickRateManager.tick(); // Folia - region threading + this.tickChildren(shouldKeepTicking, region); // Folia - region threading + if (region == null && i - this.lastServerStatus >= MinecraftServer.STATUS_EXPIRE_TIME_NANOS) { // Folia - region threading @@ -8660,11 +8921,12 @@ index 696d075ca2883f3c37e35f983c4d020e5db89d16..84f1f7956065de039837ceeaeee30259 - --this.ticksUntilAutosave; + // Folia - region threading // Paper start - Incremental chunk and player saving + final ProfilerFiller profiler = Profiler.get(); int playerSaveInterval = io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.rate; - if (playerSaveInterval < 0) { +@@ -1675,15 +1803,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.tickCount % autosavePeriod == 0; + final boolean fullSave = autosavePeriod > 0 && io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() % autosavePeriod == 0; // Folia - region threading try { @@ -8672,51 +8934,56 @@ index 696d075ca2883f3c37e35f983c4d020e5db89d16..84f1f7956065de039837ceeaeee30259 if (playerSaveInterval > 0) { this.playerList.saveAll(playerSaveInterval); } -- for (ServerLevel level : this.getAllLevels()) { -+ for (ServerLevel level : (region == null ? this.getAllLevels() : Arrays.asList(region.world))) { // Folia - region threading +- for (final ServerLevel level : this.getAllLevels()) { ++ for (final ServerLevel level : (region == null ? this.getAllLevels() : Arrays.asList(region.world))) { // Folia - region threading if (level.paperConfig().chunks.autoSaveInterval.value() > 0) { - level.saveIncrementally(fullSave); + level.saveIncrementally(region == null && fullSave); // Folia - region threading - don't save level.dat } } } finally { -@@ -1623,30 +1737,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -+ public void tickChildren(BooleanSupplier shouldKeepTicking, io.papermc.paper.threadedregions.TickRegions.TickRegionData region) { // Folia - region threading +- protected void tickChildren(BooleanSupplier shouldKeepTicking) { ++ protected void tickChildren(BooleanSupplier shouldKeepTicking, io.papermc.paper.threadedregions.TickRegions.TickRegionData region) { // Folia - region threading + final io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData(); // Folia - regionised ticking + ProfilerFiller gameprofilerfiller = Profiler.get(); + +- this.getPlayerList().getPlayers().forEach((entityplayer) -> { + if (region == null) this.getPlayerList().getPlayers().forEach((entityplayer) -> { // Folia - region threading entityplayer.connection.suspendFlushing(); }); - MinecraftTimings.bukkitSchedulerTimer.startTiming(); // Spigot // Paper -- this.server.getScheduler().mainThreadHeartbeat(this.tickCount); // CraftBukkit +- this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit + // Folia - region threading - MinecraftTimings.bukkitSchedulerTimer.stopTiming(); // Spigot // Paper -- // Paper start - Folia scheduler API + // Paper start - Folia scheduler API - ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).tick(); - getAllLevels().forEach(level -> { -- for (final Entity entity : level.moonrise$getEntityLookup().getAllCopy()) { // Paper - rewrite chunk system +- for (final Entity entity : level.getEntities().getAll()) { - if (entity.isRemoved()) { - continue; - } @@ -8797,27 +9064,23 @@ index 696d075ca2883f3c37e35f983c4d020e5db89d16..84f1f7956065de039837ceeaeee30259 - } - } - }); -- // Paper end - Folia scheduler API -- io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CALLBACK_MANAGER.handleQueue(this.tickCount); // Paper + // Folia - region threading - moved to global tick - and moved entity scheduler to tickRegion - this.profiler.push("commandFunctions"); - MinecraftTimings.commandFunctionsTimer.startTiming(); // Spigot // Paper + // Paper end - Folia scheduler API +- io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CALLBACK_MANAGER.handleQueue(this.tickCount); // Paper ++ // Folia - region threading - moved to global tick + gameprofilerfiller.push("commandFunctions"); - this.getFunctions().tick(); + if (region == null) this.getFunctions().tick(); // Folia - region threading - TODO Purge functions - MinecraftTimings.commandFunctionsTimer.stopTiming(); // Spigot // Paper - this.profiler.popPush("levels"); + gameprofilerfiller.popPush("levels"); //Iterator iterator = this.getAllLevels().iterator(); // Paper - Throw exception on world create while being ticked; moved down -@@ -1748,7 +1825,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { + gameprofilerfiller.push(() -> { String s = String.valueOf(worldserver); -@@ -1801,7 +1875,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && this.emptyTicks >= this.pauseWhileEmptySeconds() * 20; ++ return false; // Folia - region threading + } + + public void addPluginAllowingSleep(final String pluginName, final boolean value) { +- if (!value) { +- this.pluginsBlockingSleep.add(pluginName); +- } else { +- this.pluginsBlockingSleep.remove(pluginName); +- } ++ // Folia - region threading + } + + private void removeDisabledPluginsBlockingSleep() { +- if (this.pluginsBlockingSleep.isEmpty()) { +- return; +- } +- this.pluginsBlockingSleep.removeIf(plugin -> ( +- !io.papermc.paper.plugin.manager.PaperPluginManagerImpl.getInstance().isPluginEnabled(plugin) +- )); ++ // Folia - region threading + } + // Paper end - API to check if the server is sleeping + } diff --git a/src/main/java/net/minecraft/server/commands/AdvancementCommands.java b/src/main/java/net/minecraft/server/commands/AdvancementCommands.java -index 69871f95df96105a1f4ff2a8d7f1ffbd00a03c39..337c639e51e7b648d31effa62e84c447783cc92b 100644 +index 9113e1ae4d63941d8c30f366b15cf649f063e1a6..6e0b85bf57670c743e0e8bb0a996614a9108f8eb 100644 --- a/src/main/java/net/minecraft/server/commands/AdvancementCommands.java +++ b/src/main/java/net/minecraft/server/commands/AdvancementCommands.java -@@ -268,7 +268,12 @@ public class AdvancementCommands { +@@ -256,7 +256,12 @@ public class AdvancementCommands { int i = 0; for (ServerPlayer serverPlayer : targets) { @@ -8982,7 +9268,7 @@ index 69871f95df96105a1f4ff2a8d7f1ffbd00a03c39..337c639e51e7b648d31effa62e84c447 } if (i == 0) { -@@ -332,9 +337,12 @@ public class AdvancementCommands { +@@ -320,9 +325,12 @@ public class AdvancementCommands { throw ERROR_CRITERION_NOT_FOUND.create(Advancement.name(advancement), criterion); } else { for (ServerPlayer serverPlayer : targets) { @@ -9198,7 +9484,7 @@ index 4e6171ca870649114d4c7460baad2982173da09e..f8f0d33c663e6b9adac9f7e3eb21b5a6 if (i == 0) { diff --git a/src/main/java/net/minecraft/server/commands/DamageCommand.java b/src/main/java/net/minecraft/server/commands/DamageCommand.java -index 43121f35a944fd9f8d4c5f1cc53749e79892478e..737c815cb0453b2bfafd59857c443e1cf333c23f 100644 +index 4184f5e8785b54694108cbbb231cab503803109d..d8a64ca978545c0ff9957fa828b07912ed03f377 100644 --- a/src/main/java/net/minecraft/server/commands/DamageCommand.java +++ b/src/main/java/net/minecraft/server/commands/DamageCommand.java @@ -104,12 +104,29 @@ public class DamageCommand { @@ -9212,14 +9498,14 @@ index 43121f35a944fd9f8d4c5f1cc53749e79892478e..737c815cb0453b2bfafd59857c443e1c + // Folia end - region threading + private static int damage(CommandSourceStack source, Entity target, float amount, DamageSource damageSource) throws CommandSyntaxException { -- if (target.hurt(damageSource, amount)) { +- if (target.hurtServer(source.getLevel(), damageSource, amount)) { - source.sendSuccess(() -> Component.translatable("commands.damage.success", amount, target.getDisplayName()), true); - return 1; + // Folia start - region threading + target.getBukkitEntity().taskScheduler.schedule((Entity nmsEntity) -> { + try { + // Folia end - region threading -+ if (nmsEntity.hurt(damageSource, amount)) { // Folia - region threading ++ if (nmsEntity.hurtServer(source.getLevel(), damageSource, amount)) { // Folia - region threading + source.sendSuccess(() -> Component.translatable("commands.damage.success", amount, nmsEntity.getDisplayName()), true); // Folia - region threading + return; // Folia - region threading } else { @@ -9312,10 +9598,10 @@ index ed6336065a0061af095d3395b927b8976443cb68..5a6f53cfaded2df14a82ee7639cdd0bb } diff --git a/src/main/java/net/minecraft/server/commands/EnchantCommand.java b/src/main/java/net/minecraft/server/commands/EnchantCommand.java -index 99695e38b6a10c3cffda6e453f9f0619c7406cc0..69a7f9f5dc69836a472af3b4d31c6fefd028505c 100644 +index cf0a5943f457c532958f40b4989fa18f967abae6..10422cbac32c7dfbd65cda3157f30b4d4c5ce9a2 100644 --- a/src/main/java/net/minecraft/server/commands/EnchantCommand.java +++ b/src/main/java/net/minecraft/server/commands/EnchantCommand.java -@@ -68,51 +68,78 @@ public class EnchantCommand { +@@ -68,51 +68,79 @@ public class EnchantCommand { ); } @@ -9345,7 +9631,8 @@ index 99695e38b6a10c3cffda6e453f9f0619c7406cc0..69a7f9f5dc69836a472af3b4d31c6fef - itemStack.enchant(enchantment, level); - i++; - } else if (targets.size() == 1) { -- throw ERROR_INCOMPATIBLE.create(itemStack.getItem().getName(itemStack).getString()); +- throw ERROR_INCOMPATIBLE.create(itemStack.getHoverName().getString()); ++ + // Folia start - region threading + entity.getBukkitEntity().taskScheduler.schedule((LivingEntity nmsEntity) -> { + try { @@ -9358,7 +9645,7 @@ index 99695e38b6a10c3cffda6e453f9f0619c7406cc0..69a7f9f5dc69836a472af3b4d31c6fef + possibleSingleDisplayName.set(livingEntity.getDisplayName()); + changed.incrementAndGet(); + } else if (targets.size() == 1) { -+ throw ERROR_INCOMPATIBLE.create(itemStack.getItem().getName(itemStack).getString()); ++ throw ERROR_INCOMPATIBLE.create(itemStack.getHoverName().getString()); + } + } else if (targets.size() == 1) { + throw ERROR_NO_ITEM.create(livingEntity.getName().getString()); @@ -9414,7 +9701,7 @@ index 99695e38b6a10c3cffda6e453f9f0619c7406cc0..69a7f9f5dc69836a472af3b4d31c6fef + // Folia end - region threading } diff --git a/src/main/java/net/minecraft/server/commands/ExperienceCommand.java b/src/main/java/net/minecraft/server/commands/ExperienceCommand.java -index 775eb9fd56c2d0eafcfb04ab97ddb270ba3faca9..a5a69f87fe9d35c489a57d4d93e9ad54ed458d30 100644 +index a1f6d753e99e5a6a775e2dcf2a180b76d6445608..82a22e59a02333a763f36f445f3a5f4301f131dd 100644 --- a/src/main/java/net/minecraft/server/commands/ExperienceCommand.java +++ b/src/main/java/net/minecraft/server/commands/ExperienceCommand.java @@ -131,14 +131,18 @@ public class ExperienceCommand { @@ -9455,7 +9742,7 @@ index 775eb9fd56c2d0eafcfb04ab97ddb270ba3faca9..a5a69f87fe9d35c489a57d4d93e9ad54 if (i == 0) { diff --git a/src/main/java/net/minecraft/server/commands/FillBiomeCommand.java b/src/main/java/net/minecraft/server/commands/FillBiomeCommand.java -index c5bba5ce879b336b43e742eaa21d661dcee379aa..0eda57c785bec699156b2b39919b35046dacb586 100644 +index 4034f52c4fcedf30b6c79b73f47afe1a97888202..d6f98bbfcb57dade34834fca87b4209c5f5d002f 100644 --- a/src/main/java/net/minecraft/server/commands/FillBiomeCommand.java +++ b/src/main/java/net/minecraft/server/commands/FillBiomeCommand.java @@ -106,6 +106,16 @@ public class FillBiomeCommand { @@ -9487,7 +9774,7 @@ index c5bba5ce879b336b43e742eaa21d661dcee379aa..0eda57c785bec699156b2b39919b3504 + (boundingBox.minZ() - buffer) >> 4, + (boundingBox.maxZ() + buffer) >> 4, + net.minecraft.world.level.chunk.status.ChunkStatus.FULL, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, ++ ca.spottedleaf.concurrentutil.util.Priority.NORMAL, + (chunks) -> { + sendMessage(feedbackConsumer, () -> { List list = new ArrayList<>(); @@ -9506,7 +9793,7 @@ index c5bba5ce879b336b43e742eaa21d661dcee379aa..0eda57c785bec699156b2b39919b3504 } diff --git a/src/main/java/net/minecraft/server/commands/FillCommand.java b/src/main/java/net/minecraft/server/commands/FillCommand.java -index 0509e28f79d13615b5baefc34799b0ad2df071be..b4cc5328964a80c0f1f24085afd3831a4d7611e7 100644 +index 0509e28f79d13615b5baefc34799b0ad2df071be..d52a31656f2ade6d860cee6bc2f7d92a0588d643 100644 --- a/src/main/java/net/minecraft/server/commands/FillCommand.java +++ b/src/main/java/net/minecraft/server/commands/FillCommand.java @@ -151,6 +151,12 @@ public class FillCommand { @@ -9535,7 +9822,7 @@ index 0509e28f79d13615b5baefc34799b0ad2df071be..b4cc5328964a80c0f1f24085afd3831a + (range.minZ() - buffer) >> 4, + (range.maxZ() + buffer) >> 4, + net.minecraft.world.level.chunk.status.ChunkStatus.FULL, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, ++ ca.spottedleaf.concurrentutil.util.Priority.NORMAL, + (chunks) -> { + try { // Folia end - region threading int k = 0; @@ -9696,22 +9983,22 @@ index 0d9de4c61c7b26a6ff37c12fde629161fd0c3d5a..fca164cd59f1f0bf396e82a4c824c8d7 } diff --git a/src/main/java/net/minecraft/server/commands/KillCommand.java b/src/main/java/net/minecraft/server/commands/KillCommand.java -index c2974a6bd6851b54d1df2689195d896baf4906ee..57f5c571e63355b0e32480f31b9e5c8173d840c6 100644 +index e8ab673921c8089a35a2e678d7a6efed1f728cd7..287681a351f49eabd4f480396314a882bee73645 100644 --- a/src/main/java/net/minecraft/server/commands/KillCommand.java +++ b/src/main/java/net/minecraft/server/commands/KillCommand.java @@ -24,7 +24,9 @@ public class KillCommand { private static int kill(CommandSourceStack source, Collection targets) { for (Entity entity : targets) { -- entity.kill(); -+ entity.getBukkitEntity().taskScheduler.schedule((nmsEntity) -> { // Folia - region threading -+ nmsEntity.kill(); // Folia - region threading +- entity.kill(source.getLevel()); ++ entity.getBukkitEntity().taskScheduler.schedule((Entity nmsEntity) -> { // Folia - region threading ++ nmsEntity.kill((net.minecraft.server.level.ServerLevel)nmsEntity.level()); // Folia - region threading + }, null, 1L); // Folia - region threading } if (targets.size() == 1) { diff --git a/src/main/java/net/minecraft/server/commands/PlaceCommand.java b/src/main/java/net/minecraft/server/commands/PlaceCommand.java -index 00fe31a486121eabd6c1e6fc85b94ecede8a609e..351b3cb441a0700d961148239f4afed9ed5dcb57 100644 +index 07fb6f43a5a0e26b3192ac38b18f5de8d2cbf769..fd4321372985213c0605dd83221caa98e826e96d 100644 --- a/src/main/java/net/minecraft/server/commands/PlaceCommand.java +++ b/src/main/java/net/minecraft/server/commands/PlaceCommand.java @@ -88,12 +88,25 @@ public class PlaceCommand { @@ -9733,7 +10020,7 @@ index 00fe31a486121eabd6c1e6fc85b94ecede8a609e..351b3cb441a0700d961148239f4afed9 + // Folia start - region threading + worldserver.moonrise$loadChunksAsync( + pos, 16, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, ++ ca.spottedleaf.concurrentutil.util.Priority.NORMAL, + (chunks) -> { + try { + // Folia end - region threading @@ -9765,7 +10052,7 @@ index 00fe31a486121eabd6c1e6fc85b94ecede8a609e..351b3cb441a0700d961148239f4afed9 + // Folia start - region threading + worldserver.moonrise$loadChunksAsync( + pos, 16, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, ++ ca.spottedleaf.concurrentutil.util.Priority.NORMAL, + (chunks) -> { + try { + // Folia end - region threading @@ -9795,7 +10082,7 @@ index 00fe31a486121eabd6c1e6fc85b94ecede8a609e..351b3cb441a0700d961148239f4afed9 + // Folia start - region threading + worldserver.moonrise$loadChunksAsync( + pos, 16, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, ++ ca.spottedleaf.concurrentutil.util.Priority.NORMAL, + (chunks) -> { + try { + // Folia end - region threading @@ -9824,7 +10111,7 @@ index 00fe31a486121eabd6c1e6fc85b94ecede8a609e..351b3cb441a0700d961148239f4afed9 + // Folia start - region threading + worldserver.moonrise$loadChunksAsync( + pos, 16, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, ++ ca.spottedleaf.concurrentutil.util.Priority.NORMAL, + (chunks) -> { + try { + // Folia end - region threading @@ -9851,10 +10138,10 @@ index 00fe31a486121eabd6c1e6fc85b94ecede8a609e..351b3cb441a0700d961148239f4afed9 private static void checkLoaded(ServerLevel world, ChunkPos pos1, ChunkPos pos2) throws CommandSyntaxException { diff --git a/src/main/java/net/minecraft/server/commands/RecipeCommand.java b/src/main/java/net/minecraft/server/commands/RecipeCommand.java -index 869eceace975ae0a14e6be27f4c0d0e77afd715a..f8635a3beb5433269e3e7b7dc6c7f456783fd939 100644 +index dabb43ffe0e9e8aef0aa275c48ab7fdba03762cc..eb55ca5730588d2f7f1d6e80f8cb43a1955c44cb 100644 --- a/src/main/java/net/minecraft/server/commands/RecipeCommand.java +++ b/src/main/java/net/minecraft/server/commands/RecipeCommand.java -@@ -83,7 +83,12 @@ public class RecipeCommand { +@@ -81,7 +81,12 @@ public class RecipeCommand { int i = 0; for (ServerPlayer serverPlayer : targets) { @@ -9868,7 +10155,7 @@ index 869eceace975ae0a14e6be27f4c0d0e77afd715a..f8635a3beb5433269e3e7b7dc6c7f456 } if (i == 0) { -@@ -105,7 +110,12 @@ public class RecipeCommand { +@@ -103,7 +108,12 @@ public class RecipeCommand { int i = 0; for (ServerPlayer serverPlayer : targets) { @@ -9944,7 +10231,7 @@ index 15db9368227dbc29d07d74e85bd126b345b526b6..161ae9c5f9ff0e8cdf3bb3c6bb1d0686 } // Paper end - Add PlayerSetSpawnEvent diff --git a/src/main/java/net/minecraft/server/commands/SummonCommand.java b/src/main/java/net/minecraft/server/commands/SummonCommand.java -index 798999be50d26be357ef3c6d5b9383ce4d1048c1..af9b3ea74379d52f2ff08cb81e87a0a61062097a 100644 +index f635da34335cd2901adf975fcd74c5c6f9785836..fb80b635d279a18758c6b0ce99858326bcade38e 100644 --- a/src/main/java/net/minecraft/server/commands/SummonCommand.java +++ b/src/main/java/net/minecraft/server/commands/SummonCommand.java @@ -64,11 +64,18 @@ public class SummonCommand { @@ -9952,13 +10239,13 @@ index 798999be50d26be357ef3c6d5b9383ce4d1048c1..af9b3ea74379d52f2ff08cb81e87a0a6 throw SummonCommand.ERROR_FAILED.create(); } else { - if (initialize && entity instanceof Mob) { -- ((Mob) entity).finalizeSpawn(source.getLevel(), source.getLevel().getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.COMMAND, (SpawnGroupData) null); +- ((Mob) entity).finalizeSpawn(source.getLevel(), source.getLevel().getCurrentDifficultyAt(entity.blockPosition()), EntitySpawnReason.COMMAND, (SpawnGroupData) null); - } + // Folia start - region threading + io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue( + worldserver, entity.chunkPosition().x, entity.chunkPosition().z, () -> { + if (initialize && entity instanceof Mob) { -+ ((Mob) entity).finalizeSpawn(source.getLevel(), source.getLevel().getCurrentDifficultyAt(entity.blockPosition()), MobSpawnType.COMMAND, (SpawnGroupData) null); ++ ((Mob) entity).finalizeSpawn(source.getLevel(), source.getLevel().getCurrentDifficultyAt(entity.blockPosition()), EntitySpawnReason.COMMAND, (SpawnGroupData) null); + } + worldserver.tryAddFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.COMMAND); + } @@ -9971,21 +10258,21 @@ index 798999be50d26be357ef3c6d5b9383ce4d1048c1..af9b3ea74379d52f2ff08cb81e87a0a6 } else { return entity; diff --git a/src/main/java/net/minecraft/server/commands/TeleportCommand.java b/src/main/java/net/minecraft/server/commands/TeleportCommand.java -index 54851f6cc0d5fddb32a9a1e84a4f5ae41af18758..4a13ac9f5342a1b8dc155431eb33f045f87c9196 100644 +index c13b6f14c3061710c2b27034db240cc94ec0fcb5..854897f5fcc8109a69cabc7d4fef1a23289d2733 100644 --- a/src/main/java/net/minecraft/server/commands/TeleportCommand.java +++ b/src/main/java/net/minecraft/server/commands/TeleportCommand.java -@@ -77,7 +77,7 @@ public class TeleportCommand { +@@ -75,7 +75,7 @@ public class TeleportCommand { while (iterator.hasNext()) { Entity entity1 = (Entity) iterator.next(); -- TeleportCommand.performTeleport(source, entity1, (ServerLevel) destination.level(), destination.getX(), destination.getY(), destination.getZ(), EnumSet.noneOf(RelativeMovement.class), destination.getYRot(), destination.getXRot(), (TeleportCommand.LookAt) null); +- TeleportCommand.performTeleport(source, entity1, (ServerLevel) destination.level(), destination.getX(), destination.getY(), destination.getZ(), EnumSet.noneOf(Relative.class), destination.getYRot(), destination.getXRot(), (LookAt) null); + io.papermc.paper.threadedregions.TeleportUtils.teleport(entity1, false, destination, Float.valueOf(destination.getYRot()), Float.valueOf(destination.getXRot()), Entity.TELEPORT_FLAG_LOAD_CHUNK, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.COMMAND, null); // Folia - region threading } if (targets.size() == 1) { -@@ -161,6 +161,24 @@ public class TeleportCommand { - float f2 = Mth.wrapDegrees(yaw); - float f3 = Mth.wrapDegrees(pitch); +@@ -173,6 +173,24 @@ public class TeleportCommand { + float f4 = Mth.wrapDegrees(f2); + float f5 = Mth.wrapDegrees(f3); + // Folia start - region threading + if (true) { @@ -10269,35 +10556,32 @@ index 812f2adc6fc20aa126e629284fe594a923b24540..0a5e6961fb37e9a53cd39b1bd233e020 } } diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index dd56c8e041116ef3602a9f89c998c8208ab89b51..301d7fa29fce2997a5881b3852896eff5af33672 100644 +index 17a158ff6ce6520b69a5a0032ba4c05449dd0cf8..78f33298e809a7f6d079d9f2c64e2caa47a1b25a 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -469,9 +469,9 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - } - +@@ -451,7 +451,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface @Override -- public void tickChildren(BooleanSupplier shouldKeepTicking) { -- super.tickChildren(shouldKeepTicking); + public void tickConnection() { + super.tickConnection(); - this.handleConsoleInputs(); -+ public void tickChildren(BooleanSupplier shouldKeepTicking, io.papermc.paper.threadedregions.TickRegions.TickRegionData region) { // Folia - region threading -+ super.tickChildren(shouldKeepTicking, region); // Folia - region threading -+ if (region == null) this.handleConsoleInputs(); // Folia - region threading ++ // Folia - region threading } @Override -@@ -792,7 +792,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - Waitable[] waitableArray = new Waitable[1]; // Paper +@@ -768,7 +768,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + + public String runCommand(RconConsoleSource rconConsoleSource, String s) { rconConsoleSource.prepareForCommand(); - final java.util.concurrent.atomic.AtomicReference command = new java.util.concurrent.atomic.AtomicReference<>(s); // Paper - this.executeBlocking(() -> { ++ final java.util.concurrent.atomic.AtomicReference command = new java.util.concurrent.atomic.AtomicReference<>(s); // Folia start - region threading + Runnable sync = () -> { // Folia - region threading CommandSourceStack wrapper = rconConsoleSource.createCommandSourceStack(); RemoteServerCommandEvent event = new RemoteServerCommandEvent(rconConsoleSource.getBukkitSender(wrapper), s); this.server.getPluginManager().callEvent(event); -@@ -816,7 +816,16 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -777,7 +778,16 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + } ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), wrapper); this.server.dispatchServerCommand(event.getSender(), serverCommand); - } // Paper - }); + }; // Folia start - region threading + java.util.concurrent.CompletableFuture @@ -10309,14 +10593,14 @@ index dd56c8e041116ef3602a9f89c998c8208ab89b51..301d7fa29fce2997a5881b3852896eff + }) + .join(); + // Folia end - region threading - // Paper start - if (waitableArray[0] != null) { - //noinspection unchecked + return rconConsoleSource.getCommandResponse(); + // CraftBukkit end + } diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788eb684bd0 100644 +index 5b3a886c624b36557cbfaccdc3fb05a46a4ba36a..48fc7676252dbff47f59b65e6b9d9410e25778c5 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -138,8 +138,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -139,8 +139,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public final ChunkMap.ChunkDistanceManager distanceManager; public final AtomicInteger tickingGenerated; // Paper - public private final String storageName; @@ -10325,9 +10609,9 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 + //private final PlayerMap playerMap; // Folia - region threading + //public final Int2ObjectMap entityMap; // Folia - region threading private final Long2ByteMap chunkTypeCache; - private final Long2LongMap chunkSaveCooldowns; // Paper - rewrite chunk system -@@ -178,8 +178,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + public int serverViewDistance; +@@ -185,8 +185,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // Paper - rewrite chunk system this.toDrop = new LongOpenHashSet(); this.tickingGenerated = new AtomicInteger(); @@ -10336,27 +10620,9 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 + //this.playerMap = new PlayerMap(); // Folia - region threading + //this.entityMap = new Int2ObjectOpenHashMap(); // Folia - region threading this.chunkTypeCache = new Long2ByteOpenHashMap(); - this.chunkSaveCooldowns = new Long2LongOpenHashMap(); // Paper - rewrite chunk system -@@ -693,7 +693,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - if (!this.distanceManager.hasPlayersNearby(chunkcoordintpair.toLong())) { - return false; - } else { -- Iterator iterator = this.playerMap.getAllPlayers().iterator(); -+ Iterator iterator = this.level.getLocalPlayers().iterator(); // Folia - region threading - - ServerPlayer entityplayer; - -@@ -725,7 +725,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - return List.of(); - } else { - Builder builder = ImmutableList.builder(); -- Iterator iterator = this.playerMap.getAllPlayers().iterator(); -+ Iterator iterator = this.level.getLocalPlayers().iterator(); // Folia - region threading - - while (iterator.hasNext()) { - ServerPlayer entityplayer = (ServerPlayer) iterator.next(); -@@ -755,13 +755,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + Path path = session.getDimensionPath(world.dimension()); +@@ -802,13 +802,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider void updatePlayerStatus(ServerPlayer player, boolean added) { boolean flag1 = this.skipPlayer(player); @@ -10373,7 +10639,7 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 ((ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickDistanceManager)this.distanceManager).moonrise$addPlayer(player, SectionPos.of(player)); // Paper - chunk tick iteration optimisation } -@@ -770,9 +770,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -817,9 +817,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } else { SectionPos sectionposition = player.getLastSectionPos(); @@ -10386,7 +10652,7 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 ((ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickDistanceManager)this.distanceManager).moonrise$removePlayer(player, SectionPos.of(player)); // Paper - chunk tick iteration optimisation } -@@ -792,28 +792,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -839,28 +839,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider SectionPos sectionposition = player.getLastSectionPos(); SectionPos sectionposition1 = SectionPos.of((EntityAccess) player); @@ -10420,7 +10686,7 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 // Paper - rewrite chunk system } -@@ -844,9 +830,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -891,9 +877,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider public void addEntity(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot // Paper start - ignore and warn about illegal addEntity calls instead of crashing server @@ -10432,7 +10698,7 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 return; } // Paper end - ignore and warn about illegal addEntity calls instead of crashing server -@@ -859,32 +845,30 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -906,32 +892,30 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider if (i != 0) { int j = entitytypes.updateInterval(); @@ -10473,7 +10739,7 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 } } -@@ -896,16 +880,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -943,16 +927,16 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider org.spigotmc.AsyncCatcher.catchOp("entity untrack"); // Spigot if (entity instanceof ServerPlayer entityplayer) { this.updatePlayerStatus(entityplayer, false); @@ -10497,12 +10763,11 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 if (playerchunkmap_entitytracker1 != null) { playerchunkmap_entitytracker1.broadcastRemoved(); -@@ -916,10 +900,11 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -963,9 +947,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // Paper start - optimise entity tracker private void newTrackerTick() { + final io.papermc.paper.threadedregions.RegionizedWorldData worldData = this.level.getCurrentWorldData(); // Folia - region threading - final ca.spottedleaf.moonrise.common.misc.NearbyPlayers nearbyPlayers = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getNearbyPlayers(); final ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup entityLookup = (ca.spottedleaf.moonrise.patches.chunk_system.level.entity.server.ServerEntityLookup)((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getEntityLookup();; - final ca.spottedleaf.moonrise.common.list.ReferenceList trackerEntities = entityLookup.trackerEntities; @@ -10510,23 +10775,13 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 final Entity[] trackerEntitiesRaw = trackerEntities.getRawDataUnchecked(); for (int i = 0, len = trackerEntities.size(); i < len; ++i) { final Entity entity = trackerEntitiesRaw[i]; -@@ -932,7 +917,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - - // process unloads -- final ca.spottedleaf.moonrise.common.list.ReferenceList unloadedEntities = entityLookup.trackerUnloadedEntities; -+ final ca.spottedleaf.moonrise.common.list.ReferenceList unloadedEntities = worldData.trackerUnloadedEntities; // Folia - region threading - final Entity[] unloadedEntitiesRaw = java.util.Arrays.copyOf(unloadedEntities.getRawDataUnchecked(), unloadedEntities.size()); - unloadedEntities.clear(); - -@@ -955,51 +940,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -991,47 +976,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider // Paper end - optimise entity tracker // Paper - rewrite chunk system - List list = Lists.newArrayList(); - List list1 = this.level.players(); - ObjectIterator objectiterator = this.entityMap.values().iterator(); -- level.timings.tracker1.startTiming(); // Paper - - ChunkMap.TrackedEntity playerchunkmap_entitytracker; - @@ -10551,17 +10806,14 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 - playerchunkmap_entitytracker.serverEntity.sendChanges(); - } - } -- level.timings.tracker1.stopTiming(); // Paper - - if (!list.isEmpty()) { - objectiterator = this.entityMap.values().iterator(); - -- level.timings.tracker2.startTiming(); // Paper - while (objectiterator.hasNext()) { - playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); - playerchunkmap_entitytracker.updatePlayers(list); - } -- level.timings.tracker2.stopTiming(); // Paper - } + // Folia - region threading @@ -10573,7 +10825,7 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 if (playerchunkmap_entitytracker != null) { playerchunkmap_entitytracker.broadcast(packet); -@@ -1008,7 +954,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1040,7 +990,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } protected void broadcastAndSend(Entity entity, Packet packet) { @@ -10582,7 +10834,7 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 if (playerchunkmap_entitytracker != null) { playerchunkmap_entitytracker.broadcastAndSend(packet); -@@ -1256,9 +1202,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -1293,9 +1243,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } flag = flag && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z); // Paper end - Configurable entity tracking range by Y @@ -10599,10 +10851,10 @@ index af8cb316ac169aa8d98a88765b85bb013b9ba961..6f746f5ce9751dce4912f7633c126788 } // CraftBukkit end diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java -index 2d2596f04f5addac38037a14a02c6e0622d0c485..ddfbdd7c07be201bbb29fa980b6ba83216704bb0 100644 +index 7a9e7fc688e48d18a6a884f02f768ae652326aae..7d8f3e295210fcae66309ee9dd40efe1269aa712 100644 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java +++ b/src/main/java/net/minecraft/server/level/DistanceManager.java -@@ -62,16 +62,16 @@ public abstract class DistanceManager implements ca.spottedleaf.moonrise.patches +@@ -59,16 +59,16 @@ public abstract class DistanceManager implements ca.spottedleaf.moonrise.patches } // Paper end - rewrite chunk system // Paper start - chunk tick iteration optimisation @@ -10622,7 +10874,7 @@ index 2d2596f04f5addac38037a14a02c6e0622d0c485..ddfbdd7c07be201bbb29fa980b6ba832 } @Override -@@ -79,9 +79,9 @@ public abstract class DistanceManager implements ca.spottedleaf.moonrise.patches +@@ -76,9 +76,9 @@ public abstract class DistanceManager implements ca.spottedleaf.moonrise.patches final SectionPos oldPos, final SectionPos newPos, final boolean oldIgnore, final boolean newIgnore) { if (newIgnore) { @@ -10634,7 +10886,7 @@ index 2d2596f04f5addac38037a14a02c6e0622d0c485..ddfbdd7c07be201bbb29fa980b6ba832 } } // Paper end - chunk tick iteration optimisation -@@ -216,11 +216,11 @@ public abstract class DistanceManager implements ca.spottedleaf.moonrise.patches +@@ -213,15 +213,15 @@ public abstract class DistanceManager implements ca.spottedleaf.moonrise.patches } public int getNaturalSpawnChunkCount() { @@ -10647,12 +10899,17 @@ index 2d2596f04f5addac38037a14a02c6e0622d0c485..ddfbdd7c07be201bbb29fa980b6ba832 + return this.moonrise$getChunkMap().level.getCurrentWorldData().spawnChunkTracker.hasObjectsNear(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(chunkPos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(chunkPos)); // Paper - chunk tick iteration optimisation // Folia - region threading } + public LongIterator getSpawnCandidateChunks() { +- return this.spawnChunkTracker.getPositions().iterator(); // Paper - chunk tick iteration optimisation ++ return this.moonrise$getChunkMap().level.getCurrentWorldData().spawnChunkTracker.getPositions().iterator(); // Paper - chunk tick iteration optimisation // Folia - region threading + } + public String getDebugStatus() { diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index dcb5651d1d9b10b40430fb2f713beedf68336704..b0e41b79d357f7e1b189985b4752accc78f05bbb 100644 +index 82110c9af65479a918ba519e197ba880f5fcc24d..f58dadcf5f3822fd18a0d1dfb775b3d7cd7abde9 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -57,16 +57,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -62,18 +62,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon public final ServerChunkCache.MainThreadExecutor mainThreadProcessor; public final ChunkMap chunkMap; private final DimensionDataStorage dataStorage; @@ -10664,14 +10921,16 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b0e41b79d357f7e1b189985b4752accc private final long[] lastChunkPos = new long[4]; private final ChunkStatus[] lastChunkStatus = new ChunkStatus[4]; private final ChunkAccess[] lastChunk = new ChunkAccess[4]; +- private final List tickingChunks = new ArrayList(); +- private final Set chunkHoldersToBroadcast = new ReferenceOpenHashSet(); - @Nullable - @VisibleForDebug - private NaturalSpawner.SpawnState lastSpawnState; + // Folia - moved to regionised world data // Paper start private final ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable fullChunks = new ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<>(); - long chunkFutureAwaitCounter; -@@ -89,6 +87,11 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + public int getFullChunksCount() { +@@ -99,6 +95,11 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } private ChunkAccess syncLoad(final int chunkX, final int chunkZ, final ChunkStatus toStatus) { @@ -10683,16 +10942,7 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b0e41b79d357f7e1b189985b4752accc final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler chunkTaskScheduler = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler(); final CompletableFuture completable = new CompletableFuture<>(); chunkTaskScheduler.scheduleChunkLoad( -@@ -126,7 +129,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - return load ? this.syncLoad(chunkX, chunkZ, toStatus) : null; - } - // Paper end - rewrite chunk system -- private ServerChunkCache.ChunkAndHolder[] iterationCopy; // Paper - chunk tick iteration optimisations -+ // Folia - moved to regionized data - - public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, int simulationDistance, boolean dsync, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory) { - this.level = world; -@@ -252,6 +255,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -322,6 +323,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } public CompletableFuture> getChunkFuture(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { @@ -10700,79 +10950,117 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b0e41b79d357f7e1b189985b4752accc boolean flag1 = Thread.currentThread() == this.mainThread; CompletableFuture completablefuture; -@@ -419,11 +423,12 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -475,16 +477,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } private void tickChunks() { -+ io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.level.getCurrentWorldData(); // Folia - region threading - long chunksTicked = 0; // Paper - rewrite chunk system - long i = this.level.getGameTime(); - long j = i - this.lastInhabitedUpdate; ++ io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.level.getCurrentWorldData(); // Folia - region threading + //long i = this.level.getGameTime(); // Folia - region threading + long j = 1L; // Folia - region threading - this.lastInhabitedUpdate = i; + //this.lastInhabitedUpdate = i; // Folia - region threading if (!this.level.isDebug()) { - ProfilerFiller gameprofilerfiller = this.level.getProfiler(); + ProfilerFiller gameprofilerfiller = Profiler.get(); -@@ -438,13 +443,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - final ServerChunkCache.ChunkAndHolder[] raw = tickingChunks.getRawDataUnchecked(); - final int size = tickingChunks.size(); + gameprofilerfiller.push("pollingChunks"); + if (this.level.tickRateManager().runsNormally()) { +- List list = this.tickingChunks; ++ List list = regionizedWorldData.temporaryChunkTickList; // Folia - region threading -- if (this.iterationCopy == null || this.iterationCopy.length < size) { -- this.iterationCopy = new ServerChunkCache.ChunkAndHolder[raw.length]; -+ if (regionizedWorldData.iterationCopy == null || regionizedWorldData.iterationCopy.length < size) { // Folia - region threading -+ regionizedWorldData.iterationCopy = new ServerChunkCache.ChunkAndHolder[raw.length]; // Folia - region threading - } -- System.arraycopy(raw, 0, this.iterationCopy, 0, size); -+ System.arraycopy(raw, 0, regionizedWorldData.iterationCopy, 0, size); // Folia - region threading + try { + gameprofilerfiller.push("filteringTickingChunks"); +@@ -507,8 +510,9 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + } - list = it.unimi.dsi.fastutil.objects.ObjectArrayList.wrap( -- this.iterationCopy, size -+ regionizedWorldData.iterationCopy, size // Folia - region threading - ); + private void broadcastChangedChunks(ProfilerFiller profiler) { ++ io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.level.getCurrentWorldData(); // Folia - region threading + profiler.push("broadcast"); +- Iterator iterator = this.chunkHoldersToBroadcast.iterator(); ++ Iterator iterator = regionizedWorldData.chunkHoldersToBroadcast.iterator(); // Folia - region threading - note: do not need to thread check, as getChunkToSend is only non-null when the chunkholder is loaded + + while (iterator.hasNext()) { + ChunkHolder playerchunk = (ChunkHolder) iterator.next(); +@@ -519,14 +523,14 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } - // Paper end - chunk tick iteration optimisations -@@ -462,7 +467,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - NaturalSpawner.SpawnState spawnercreature_d; // moved down - if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled - // re-set mob counts -- for (ServerPlayer player : this.level.players) { -+ for (ServerPlayer player : this.level.getLocalPlayers()) { // Folia - region threading - // Paper start - per player mob spawning backoff - for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) { - player.mobCounts[ii] = 0; -@@ -475,23 +480,23 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - } - // Paper end - per player mob spawning backoff - } -- spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); -+ spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, null, true); // Folia - region threading - note: function only cares about loaded entities, doesn't need all - } else { -- spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); -+ spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); // Folia - region threading - note: function only cares about loaded entities, doesn't need all - } - // Paper end - Optional per player mob spawns - this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings + } -- this.lastSpawnState = spawnercreature_d; -+ regionizedWorldData.lastSpawnState = spawnercreature_d; // Folia - region threading - gameprofilerfiller.popPush("spawnAndTick"); -- boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit -+ boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.getLocalPlayers().isEmpty(); // CraftBukkit // Folia - region threadin +- this.chunkHoldersToBroadcast.clear(); ++ regionizedWorldData.chunkHoldersToBroadcast.clear(); // Folia - region threading + profiler.pop(); + } - if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.level.random); // Paper - per player mob spawns - do not need this when per-player is enabled - // Paper start - PlayerNaturallySpawnCreaturesEvent - int chunkRange = level.spigotConfig.mobSpawnRange; - chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; - chunkRange = Math.min(chunkRange, 8); -- for (ServerPlayer entityPlayer : this.level.players()) { -+ for (ServerPlayer entityPlayer : this.level.getLocalPlayers()) { // Folia - region threading - entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); - entityPlayer.playerNaturallySpawnedEvent.callEvent(); + private void collectTickingChunks(List chunks) { + // Paper start - chunk tick iteration optimisation + final ca.spottedleaf.moonrise.common.list.ReferenceList tickingChunks = +- ((ca.spottedleaf.moonrise.patches.chunk_tick_iteration.ChunkTickServerLevel)this.level).moonrise$getPlayerTickingChunks(); ++ this.level.getCurrentWorldData().getEntityTickingChunks(); // Folia - region threading + + final ServerChunkCache.ChunkAndHolder[] raw = tickingChunks.getRawDataUnchecked(); + final int size = tickingChunks.size(); +@@ -547,6 +551,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + } + + private void tickChunks(ProfilerFiller profiler, long timeDelta, List chunks) { ++ io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.level.getCurrentWorldData(); // Folia - region threading + profiler.popPush("naturalSpawnCount"); + int j = this.distanceManager.getNaturalSpawnChunkCount(); + // Paper start - Optional per player mob spawns +@@ -554,7 +559,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + NaturalSpawner.SpawnState spawnercreature_d; // moved down + if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled + // re-set mob counts +- for (ServerPlayer player : this.level.players) { ++ for (ServerPlayer player : this.level.getLocalPlayers()) { // Folia - region threading + // Paper start - per player mob spawning backoff + for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) { + player.mobCounts[ii] = 0; +@@ -567,15 +572,15 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } -@@ -604,14 +609,19 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + // Paper end - per player mob spawning backoff + } +- spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); ++ spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, null, true); // Folia - region threading - note: function only cares about loaded entities, doesn't need all + } else { +- spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); ++ spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); // Folia - region threading - note: function only cares about loaded entities, doesn't need all + } + // Paper end - Optional per player mob spawns + +- this.lastSpawnState = spawnercreature_d; ++ regionizedWorldData.lastSpawnState = spawnercreature_d; // Folia - region threading + profiler.popPush("spawnAndTick"); +- boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit ++ boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.getLocalPlayers().isEmpty(); // CraftBukkit // Folia - region threading + int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); + List list1; + +@@ -584,12 +589,12 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + int chunkRange = level.spigotConfig.mobSpawnRange; + chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; + chunkRange = Math.min(chunkRange, 8); +- for (ServerPlayer entityPlayer : this.level.players()) { ++ for (ServerPlayer entityPlayer : this.level.getLocalPlayers()) { // Folia - region threading + entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange); + entityPlayer.playerNaturallySpawnedEvent.callEvent(); + } + // Paper end - PlayerNaturallySpawnCreaturesEvent +- boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit ++ boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getRedstoneGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit // Folia - region threading + + list1 = NaturalSpawner.getFilteredSpawningCategories(spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1, this.level); // CraftBukkit + } else { +@@ -663,21 +668,26 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + ChunkHolder playerchunk = this.getVisibleChunkIfPresent(ChunkPos.asLong(i, j)); + + if (playerchunk != null && playerchunk.blockChanged(pos)) { +- this.chunkHoldersToBroadcast.add(playerchunk); ++ this.level.getCurrentWorldData().chunkHoldersToBroadcast.add(playerchunk); // Folia - region threading + } + + } @Override public void onLightUpdate(LightLayer type, SectionPos pos) { @@ -10780,8 +11068,9 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b0e41b79d357f7e1b189985b4752accc + Runnable run = () -> { // Folia - region threading ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.chunk().toLong()); - if (playerchunk != null) { - playerchunk.sectionLightChanged(type, pos.y()); + if (playerchunk != null && playerchunk.sectionLightChanged(type, pos.y())) { +- this.chunkHoldersToBroadcast.add(playerchunk); ++ this.level.getCurrentWorldData().chunkHoldersToBroadcast.add(playerchunk); // Folia - region threading } - }); @@ -10794,7 +11083,7 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b0e41b79d357f7e1b189985b4752accc } public void addRegionTicket(TicketType ticketType, ChunkPos pos, int radius, T argument) { -@@ -689,7 +699,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -761,7 +771,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @Nullable @VisibleForDebug public NaturalSpawner.SpawnState getLastSpawnState() { @@ -10804,17 +11093,42 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b0e41b79d357f7e1b189985b4752accc } public void removeTicketsOnClosing() { -@@ -729,8 +740,43 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -770,7 +781,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + + public void onChunkReadyToSend(ChunkHolder chunkHolder) { + if (chunkHolder.hasChangesToBroadcast()) { +- this.chunkHoldersToBroadcast.add(chunkHolder); ++ throw new UnsupportedOperationException(); // Folia - region threading + } + + } +@@ -808,8 +819,59 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon return ServerChunkCache.this.mainThread; } + // Folia start - region threading + @Override -+ public void tell(Runnable runnable) { ++ public CompletableFuture submit(Supplier task) { + if (true) { + throw new UnsupportedOperationException(); + } -+ super.tell(runnable); ++ return super.submit(task); ++ } ++ ++ @Override ++ public CompletableFuture submit(Runnable task) { ++ if (true) { ++ throw new UnsupportedOperationException(); ++ } ++ return super.submit(task); ++ } ++ ++ @Override ++ public void schedule(Runnable runnable) { ++ if (true) { ++ throw new UnsupportedOperationException(); ++ } ++ super.schedule(runnable); + } + + @Override @@ -10845,10 +11159,10 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b0e41b79d357f7e1b189985b4752accc @Override protected void doRunTask(Runnable task) { + if (true) throw new UnsupportedOperationException(); // Folia - region threading - ServerChunkCache.this.level.getProfiler().incrementCounter("runTask"); + Profiler.get().incrementCounter("runTask"); super.doRunTask(task); } -@@ -738,12 +784,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -817,12 +879,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @Override // CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task public boolean pollTask() { @@ -10867,41 +11181,82 @@ index dcb5651d1d9b10b40430fb2f713beedf68336704..b0e41b79d357f7e1b189985b4752accc } // Paper end - rewrite chunk system // CraftBukkit end +diff --git a/src/main/java/net/minecraft/server/level/ServerEntityGetter.java b/src/main/java/net/minecraft/server/level/ServerEntityGetter.java +index 296059746fe9f5c35fedd8ca1dea488da519ac05..7df954d6375abb83cb0b140a16336b478d13e9d8 100644 +--- a/src/main/java/net/minecraft/server/level/ServerEntityGetter.java ++++ b/src/main/java/net/minecraft/server/level/ServerEntityGetter.java +@@ -14,17 +14,17 @@ public interface ServerEntityGetter extends EntityGetter { + + @Nullable + default Player getNearestPlayer(TargetingConditions targetPredicate, LivingEntity entity) { +- return this.getNearestEntity(this.players(), targetPredicate, entity, entity.getX(), entity.getY(), entity.getZ()); ++ return this.getNearestEntity(this.getLocalPlayers(), targetPredicate, entity, entity.getX(), entity.getY(), entity.getZ()); // Folia - region threading + } + + @Nullable + default Player getNearestPlayer(TargetingConditions targetPredicate, LivingEntity entity, double x, double y, double z) { +- return this.getNearestEntity(this.players(), targetPredicate, entity, x, y, z); ++ return this.getNearestEntity(this.getLocalPlayers(), targetPredicate, entity, x, y, z); // Folia - region threading + } + + @Nullable + default Player getNearestPlayer(TargetingConditions targetPredicate, double x, double y, double z) { +- return this.getNearestEntity(this.players(), targetPredicate, null, x, y, z); ++ return this.getNearestEntity(this.getLocalPlayers(), targetPredicate, null, x, y, z); // Folia - region threading + } + + @Nullable +@@ -57,7 +57,7 @@ public interface ServerEntityGetter extends EntityGetter { + default List getNearbyPlayers(TargetingConditions targetPredicate, LivingEntity entity, AABB box) { + List list = new ArrayList<>(); + +- for (Player player : this.players()) { ++ for (Player player : this.getLocalPlayers()) { // Folia - region threading + if (box.contains(player.getX(), player.getY(), player.getZ()) && targetPredicate.test(this.getLevel(), entity, player)) { + list.add(player); + } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba5976c2b807 100644 +index b4027f5cf90935a1fe3ab2c28b0bcbb55a7b541b..f8d865c7127e7a05bb8ce34b86bc41eed8b9de23 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -198,37 +198,35 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -195,42 +195,40 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int EMPTY_TIME_NO_TICK = 300; + private static final int MAX_SCHEDULED_TICKS_PER_TICK = 65536; +- final List players = Lists.newArrayList(); ++ final List players = new java.util.concurrent.CopyOnWriteArrayList<>(); // Folia - region threading + public final ServerChunkCache chunkSource; private final MinecraftServer server; public final PrimaryLevelData serverLevelData; // CraftBukkit - type private int lastSpawnChunkRadius; -- final EntityTickList entityTickList; -+ //final EntityTickList entityTickList; // Folia - region threading +- final EntityTickList entityTickList = new EntityTickList(); ++ //final EntityTickList entityTickList = new EntityTickList(); // Folia - region threading // Paper - rewrite chunk system private final GameEventDispatcher gameEventDispatcher; public boolean noSave; private final SleepStatus sleepStatus; private int emptyTime; private final PortalForcer portalForcer; -- private final LevelTicks blockTicks; -- private final LevelTicks fluidTicks; -- private final PathTypeCache pathTypesByPosCache; -+ //private final LevelTicks blockTicks; // Folia - region threading -+ //private final LevelTicks fluidTicks; // Folia - region threading -+ //private final PathTypeCache pathTypesByPosCache; // Folia - region threading - final Set navigatingMobs; +- private final LevelTicks blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded); +- private final LevelTicks fluidTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded); +- private final PathTypeCache pathTypesByPosCache = new PathTypeCache(); +- final Set navigatingMobs = new ObjectOpenHashSet(); ++ //private final LevelTicks blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded); // Folia - region threading ++ //private final LevelTicks fluidTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded); // Folia - region threading ++ //private final PathTypeCache pathTypesByPosCache = new PathTypeCache(); // Folia - region threading ++ //final Set navigatingMobs = new ObjectOpenHashSet(); // Folia - region threading volatile boolean isUpdatingNavigations; protected final Raids raids; -- private final ObjectLinkedOpenHashSet blockEvents; -- private final List blockEventsToReschedule; +- private final ObjectLinkedOpenHashSet blockEvents = new ObjectLinkedOpenHashSet(); +- private final List blockEventsToReschedule = new ArrayList(64); - private boolean handlingTick; -+ //private final ObjectLinkedOpenHashSet blockEvents; // Folia - region threading -+ //private final List blockEventsToReschedule; // Folia - region threading ++ //private final ObjectLinkedOpenHashSet blockEvents = new ObjectLinkedOpenHashSet(); // Folia - region threading ++ //private final List blockEventsToReschedule = new ArrayList(64); // Folia - region threading + //private boolean handlingTick; // Folia - region threading private final List customSpawners; @Nullable private EndDragonFight dragonFight; - final Int2ObjectMap dragonParts; + final Int2ObjectMap dragonParts = new Int2ObjectOpenHashMap(); private final StructureManager structureManager; private final StructureCheck structureCheck; - private final boolean tickTime; @@ -10918,44 +11273,21 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 public LevelChunk getChunkIfLoaded(int x, int z) { return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately -@@ -258,6 +256,36 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - - ServerChunkCache chunkProvider = this.getChunkSource(); +@@ -258,6 +256,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + int minChunkZ = minBlockZ >> 4; + int maxChunkZ = maxBlockZ >> 4; + // Folia start - region threading + // don't let players move into regions not owned + if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this, minChunkX, minChunkZ, maxChunkX, maxChunkZ)) { + return false; + } -+ -+ for (int cx = minChunkX; cx <= maxChunkX; ++cx) { -+ for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) { -+ if (chunkProvider.getChunkAtIfLoadedImmediately(cx, cz) == null) { -+ return false; -+ } -+ } -+ } -+ -+ return true; -+ } -+ -+ public final boolean isAreaLoaded(final BlockPos center, final int radius) { -+ int minX = (center.getX() - radius) >> 4; -+ int minZ = (center.getZ() - radius) >> 4; -+ int maxX = (center.getX() + radius) >> 4; -+ int maxZ = (center.getZ() + radius) >> 4; -+ -+ return this.isAreaLoaded(minX, minZ, maxX, maxZ); -+ } -+ -+ public final boolean isAreaLoaded(final int minChunkX, final int minChunkZ, final int maxChunkX, final int maxChunkZ) { + // Folia end - region threading -+ ServerChunkCache chunkProvider = this.getChunkSource(); + + ServerChunkCache chunkProvider = this.getChunkSource(); + for (int cx = minChunkX; cx <= maxChunkX; ++cx) { - for (int cz = minChunkZ; cz <= maxChunkZ; ++cz) { - if (chunkProvider.getChunkAtIfLoadedImmediately(cx, cz) == null) { -@@ -306,11 +334,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -313,11 +318,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe private final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler chunkTaskScheduler; private long lastMidTickFailure; private long tickedBlocksOrFluids; @@ -10968,7 +11300,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 @Override public final LevelChunk moonrise$getFullChunkIfLoaded(final int chunkX, final int chunkZ) { -@@ -368,7 +392,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -375,7 +376,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @Override public final int moonrise$getRegionChunkShift() { @@ -10977,7 +11309,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } @Override -@@ -467,35 +491,87 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -474,22 +475,22 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @Override public final ca.spottedleaf.moonrise.common.misc.NearbyPlayers moonrise$getNearbyPlayers() { @@ -11002,7 +11334,92 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 - return this.entityTickingChunks; + return this.getCurrentWorldData().getEntityTickingChunks(); // Folia - region threading } + + @Override +@@ -509,91 +510,96 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // Paper end - rewrite chunk system + // Paper start - chunk tick iteration + private static final ServerChunkCache.ChunkAndHolder[] EMPTY_PLAYER_CHUNK_HOLDERS = new ServerChunkCache.ChunkAndHolder[0]; +- private final ca.spottedleaf.moonrise.common.list.ReferenceList playerTickingChunks = new ca.spottedleaf.moonrise.common.list.ReferenceList<>(EMPTY_PLAYER_CHUNK_HOLDERS); +- private final it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap playerTickingRequests = new it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap(); ++ // Folia - region threading + + @Override + public final ca.spottedleaf.moonrise.common.list.ReferenceList moonrise$getPlayerTickingChunks() { +- return this.playerTickingChunks; ++ throw new UnsupportedOperationException(); // Folia - region threading + } + + @Override + public final void moonrise$markChunkForPlayerTicking(final LevelChunk chunk) { +- final ChunkPos pos = chunk.getPos(); +- if (!this.playerTickingRequests.containsKey(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(pos))) { +- return; +- } +- +- this.playerTickingChunks.add(((ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()); ++ // Folia - region threading + } + + @Override + public final void moonrise$removeChunkForPlayerTicking(final LevelChunk chunk) { +- this.playerTickingChunks.remove(((ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk)chunk).moonrise$getChunkAndHolder()); ++ // Folia - region threading + } + + @Override + public final void moonrise$addPlayerTickingRequest(final int chunkX, final int chunkZ) { +- ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)(Object)this, chunkX, chunkZ, "Cannot add ticking request async"); +- +- final long chunkKey = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ); +- +- if (this.playerTickingRequests.addTo(chunkKey, 1) != 0) { +- // already added +- return; +- } +- +- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)(ServerLevel)(Object)this).moonrise$getChunkTaskScheduler() +- .chunkHolderManager.getChunkHolder(chunkKey); +- +- if (chunkHolder == null || !chunkHolder.isTickingReady()) { +- return; +- } +- +- this.playerTickingChunks.add( +- ((ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk)(LevelChunk)chunkHolder.getCurrentChunk()).moonrise$getChunkAndHolder() +- ); ++ // Folia - region threading + } + + @Override + public final void moonrise$removePlayerTickingRequest(final int chunkX, final int chunkZ) { +- ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)(Object)this, chunkX, chunkZ, "Cannot remove ticking request async"); +- +- final long chunkKey = ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkKey(chunkX, chunkZ); +- final int val = this.playerTickingRequests.addTo(chunkKey, -1); +- +- if (val <= 0) { +- throw new IllegalStateException("Negative counter"); +- } +- +- if (val != 1) { +- // still has at least one request +- return; +- } +- +- final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)(ServerLevel)(Object)this).moonrise$getChunkTaskScheduler() +- .chunkHolderManager.getChunkHolder(chunkKey); +- +- if (chunkHolder == null || !chunkHolder.isTickingReady()) { +- return; +- } +- +- this.playerTickingChunks.remove( +- ((ca.spottedleaf.moonrise.patches.chunk_system.level.chunk.ChunkSystemLevelChunk)(LevelChunk)chunkHolder.getCurrentChunk()).moonrise$getChunkAndHolder() +- ); ++ // Folia - region threading + } + // Paper end - chunk tick iteration // Paper start - lag compensation private long lagCompensationTick = net.minecraft.server.MinecraftServer.SERVER_INIT; @@ -11071,29 +11488,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 // Add env and gen to constructor, IWorldDataServer -> WorldDataServer public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { -@@ -508,14 +584,14 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - this.convertable = convertable_conversionsession; - this.uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); - // CraftBukkit end -- this.players = Lists.newArrayList(); -- this.entityTickList = new EntityTickList(); -- this.blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); -- this.fluidTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); -- this.pathTypesByPosCache = new PathTypeCache(); -+ this.players = new java.util.concurrent.CopyOnWriteArrayList<>(); // Folia - region threading -+ //this.entityTickList = new EntityTickList(); // Folia - region threading -+ //this.blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); // Folia - moved to RegioniedWorldData -+ //this.fluidTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); // Folia - moved to RegioniedWorldData -+ //this.pathTypesByPosCache = new PathTypeCache(); // Folia - moved to RegioniedWorldData - this.navigatingMobs = new ObjectOpenHashSet(); -- this.blockEvents = new ObjectLinkedOpenHashSet(); -- this.blockEventsToReschedule = new ArrayList(64); -+ //this.blockEvents = new ObjectLinkedOpenHashSet(); // Folia - moved to RegioniedWorldData -+ //this.blockEventsToReschedule = new ArrayList(64); // Folia - moved to RegioniedWorldData - this.dragonParts = new Int2ObjectOpenHashMap(); - this.tickTime = flag1; - this.server = minecraftserver; -@@ -553,7 +629,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -638,7 +644,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe }); this.chunkSource.getGeneratorState().ensureStructuresGenerated(); this.portalForcer = new PortalForcer(this); @@ -11102,8 +11497,8 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 this.prepareWeather(); this.getWorldBorder().setAbsoluteMaxSize(minecraftserver.getAbsoluteMaxWorldSize()); this.raids = (Raids) this.getDataStorage().computeIfAbsent(Raids.factory(this), Raids.getFileId(this.dimensionTypeRegistration())); -@@ -590,7 +666,14 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - this.chunkTaskScheduler = new ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler((ServerLevel)(Object)this, ca.spottedleaf.moonrise.common.util.MoonriseCommon.WORKER_POOL); +@@ -676,7 +682,14 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler); // Paper end - rewrite chunk system this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit + this.updateTickData(); // Folia - region threading - make sure it is initialised before ticked @@ -11117,7 +11512,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 // Paper start @Override -@@ -619,48 +702,32 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -705,60 +718,44 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe return this.getChunkSource().getGenerator().getBiomeSource().getNoiseBiome(biomeX, biomeY, biomeZ, this.getChunkSource().randomState().sampler()); } @@ -11129,7 +11524,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 - public void tick(BooleanSupplier shouldKeepTicking) { + public void tick(BooleanSupplier shouldKeepTicking, io.papermc.paper.threadedregions.TickRegions.TickRegionData region) { // Folia - regionised ticking + final io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.getCurrentWorldData(); // Folia - regionised ticking - ProfilerFiller gameprofilerfiller = this.getProfiler(); + ProfilerFiller gameprofilerfiller = Profiler.get(); - this.handlingTick = true; + regionizedWorldData.setHandlingTick(true); // Folia - regionised ticking @@ -11143,6 +11538,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 gameprofilerfiller.popPush("weather"); - this.advanceWeatherCycle(); + if (region == null) this.advanceWeatherCycle(); // Folia - regionised ticking + gameprofilerfiller.pop(); } - int i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE); @@ -11175,9 +11571,8 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 if (flag) { this.tickTime(); } -@@ -668,11 +735,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - gameprofilerfiller.popPush("tickPending"); - this.timings.scheduledBlocks.startTiming(); // Paper + + gameprofilerfiller.push("tickPending"); if (!this.isDebug() && flag) { - j = this.getGameTime(); + j = regionizedWorldData.getRedstoneGameTime(); // Folia - region threading @@ -11189,9 +11584,9 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 + regionizedWorldData.getFluidLevelTicks().tick(j, paperConfig().environment.maxFluidTicks, this::tickFluid); // Paper - configurable max fluid ticks // Folia - region ticking gameprofilerfiller.pop(); } - this.timings.scheduledBlocks.stopTiming(); // Paper -@@ -695,9 +762,9 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - this.timings.doSounds.stopTiming(); // Spigot + +@@ -774,9 +771,9 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + this.runBlockEvents(); } - this.handlingTick = false; @@ -11202,9 +11597,9 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 if (flag1) { this.resetEmptyTime(); -@@ -707,20 +774,30 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -785,17 +782,27 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + if (flag1 || this.emptyTime++ < 300) { gameprofilerfiller.push("entities"); - this.timings.tickEntities.startTiming(); // Spigot if (this.dragonFight != null && flag) { + if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this, this.dragonFight.origin)) { // Folia - region threading gameprofilerfiller.push("dragonFight"); @@ -11221,20 +11616,17 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } org.spigotmc.ActivationRange.activateEntities(this); // Spigot - this.timings.entityTick.startTiming(); // Spigot - this.entityTickList.forEach((entity) -> { + regionizedWorldData.forEachTickingEntity((entity) -> { // Folia - regionised ticking if (!entity.isRemoved()) { - if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed - entity.discard(); - } else if (!tickratemanager.isEntityFrozen(entity)) { + if (!tickratemanager.isEntityFrozen(entity)) { gameprofilerfiller.push("checkDespawn"); entity.checkDespawn(); + if (entity.isRemoved()) return; // Folia - region threading - if we despawned, DON'T TICK IT! gameprofilerfiller.pop(); - if (true || this.chunkSource.chunkMap.getDistanceManager().inEntityTickingRange(entity.chunkPosition().toLong())) { // Paper - rewrite chunk system + if (true) { // Paper - rewrite chunk system Entity entity1 = entity.getVehicle(); -@@ -751,6 +828,31 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -824,6 +831,31 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe gameprofilerfiller.pop(); } @@ -11266,7 +11658,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 @Override public boolean shouldTickBlocksAt(long chunkPos) { // Paper start - rewrite chunk system -@@ -761,11 +863,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -834,13 +866,14 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe protected void tickTime() { if (this.tickTime) { @@ -11275,15 +11667,17 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 + long i = regionizedWorldData.getRedstoneGameTime() + 1L; // Folia - region threading - this.serverLevelData.setGameTime(i); -- this.serverLevelData.getScheduledEvents().tick(this.server, i); -- if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { + regionizedWorldData.setRedstoneGameTime(i); // Folia - region threading + Profiler.get().push("scheduledFunctions"); +- this.serverLevelData.getScheduledEvents().tick(this.server, i); + if (false) this.serverLevelData.getScheduledEvents().tick(this.server, i); // Folia - region threading - TODO any way to bring this in? -+ if (false && this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { // Folia - region threading + Profiler.get().pop(); +- if (this.serverLevelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { ++ if (false && this.serverLevelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) { // Folia - region threading this.setDayTime(this.levelData.getDayTime() + 1L); } -@@ -794,7 +897,14 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -865,17 +898,24 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe private void wakeUpAllPlayers() { this.sleepStatus.removeAllSleepers(); (this.players.stream().filter(LivingEntity::isSleeping).collect(Collectors.toList())).forEach((entityplayer) -> { // CraftBukkit - decompile error @@ -11299,7 +11693,28 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 }); } -@@ -995,7 +1105,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + // Paper start - optimise random ticking +- private final ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom simpleRandom = new ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom(net.minecraft.world.level.levelgen.RandomSupport.generateUniqueSeed()); ++ private final io.papermc.paper.threadedregions.util.SimpleThreadLocalRandomSource simpleRandom = io.papermc.paper.threadedregions.util.SimpleThreadLocalRandomSource.INSTANCE; // Folia - region threading + + private void optimiseRandomTick(final LevelChunk chunk, final int tickSpeed) { + final LevelChunkSection[] sections = chunk.getSections(); + final int minSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMinSection((ServerLevel)(Object)this); +- final ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom simpleRandom = this.simpleRandom; ++ final io.papermc.paper.threadedregions.util.SimpleThreadLocalRandomSource simpleRandom = this.simpleRandom; // Folia - region threading + final boolean doubleTickFluids = !ca.spottedleaf.moonrise.common.PlatformHooks.get().configFixMC224294(); + + final ChunkPos cpos = chunk.getPos(); +@@ -922,7 +962,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + // Paper end - optimise random ticking + + public void tickChunk(LevelChunk chunk, int randomTickSpeed) { +- final ca.spottedleaf.moonrise.common.util.SimpleThreadUnsafeRandom simpleRandom = this.simpleRandom; // Paper - optimise random ticking ++ final io.papermc.paper.threadedregions.util.SimpleThreadLocalRandomSource simpleRandom = this.simpleRandom; // Paper - optimise random ticking // Folia - region threading + ChunkPos chunkcoordintpair = chunk.getPos(); + boolean flag = this.isRaining(); + int j = chunkcoordintpair.getMinBlockX(); +@@ -1060,7 +1100,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } public boolean isHandlingTick() { @@ -11308,7 +11723,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } public boolean canSleepThroughNights() { -@@ -1027,6 +1137,14 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1092,6 +1132,14 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } public void updateSleepingPlayerList() { @@ -11323,7 +11738,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 if (!this.players.isEmpty() && this.sleepStatus.update(this.players)) { this.announceSleepStatus(); } -@@ -1038,7 +1156,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1103,7 +1151,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe return this.server.getScoreboard(); } @@ -11332,7 +11747,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 boolean flag = this.isRaining(); if (this.dimensionType().hasSkyLight()) { -@@ -1124,23 +1242,24 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1189,23 +1237,24 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.server.getPlayerList().broadcastAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, this.thunderLevel)); } // */ @@ -11366,9 +11781,36 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } } // CraftBukkit end -@@ -1246,7 +1365,16 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1267,13 +1316,10 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + + // Paper start - log detailed entity tick information + // TODO replace with varhandle +- static final java.util.concurrent.atomic.AtomicReference currentlyTickingEntity = new java.util.concurrent.atomic.AtomicReference<>(); ++ // Folia - region threading + + public static List getCurrentlyTickingEntities() { +- Entity ticking = currentlyTickingEntity.get(); +- List ret = java.util.Arrays.asList(ticking == null ? new Entity[0] : new Entity[] { ticking }); +- +- return ret; ++ throw new UnsupportedOperationException(); // Folia - region threading + } + // Paper end - log detailed entity tick information + +@@ -1281,9 +1327,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + // Paper start - log detailed entity tick information + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread("Cannot tick an entity off-main"); + try { +- if (currentlyTickingEntity.get() == null) { +- currentlyTickingEntity.lazySet(entity); +- } ++ // Folia - region threading + // Paper end - log detailed entity tick information + // Spigot start + /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out EAR 2 +@@ -1303,7 +1347,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); // Paper - EAR 2 if (isActive) { // Paper - EAR 2 - TimingHistory.activatedEntityTicks++; entity.tick(); - entity.postTick(); // CraftBukkit + // Folia start - region threading @@ -11382,18 +11824,28 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 + } + // Folia end - region threading } else { entity.inactiveTick(); } // Paper - EAR 2 - this.getProfiler().pop(); - } finally { timer.stopTiming(); } // Paper - timings -@@ -1269,7 +1397,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + gameprofilerfiller.pop(); + Iterator iterator = entity.getPassengers().iterator(); +@@ -1316,16 +1369,14 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - private void tickPassenger(Entity vehicle, Entity passenger) { + // Paper start - log detailed entity tick information + } finally { +- if (currentlyTickingEntity.get() == entity) { +- currentlyTickingEntity.lazySet(null); +- } ++ // Folia - region threading + } + // Paper end - log detailed entity tick information + } + + private void tickPassenger(Entity vehicle, Entity passenger, boolean isActive) { // Paper - EAR 2 if (!passenger.isRemoved() && passenger.getVehicle() == vehicle) { - if (passenger instanceof Player || this.entityTickList.contains(passenger)) { + if (passenger instanceof Player || this.getCurrentWorldData().hasEntityTickingEntity(passenger)) { // Folia - region threading - // Paper - EAR 2 - final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); - co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper -@@ -1286,7 +1414,16 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + passenger.setOldPosAndRot(); + ++passenger.tickCount; + ProfilerFiller gameprofilerfiller = Profiler.get(); +@@ -1337,7 +1388,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // Paper start - EAR 2 if (isActive) { passenger.rideTick(); @@ -11409,9 +11861,9 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 + } + // Folia end - region threading } else { - passenger.setDeltaMovement(Vec3.ZERO); - passenger.inactiveTick(); -@@ -1381,20 +1518,22 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + passenger.setDeltaMovement(Vec3.ZERO); + passenger.inactiveTick(); +@@ -1422,19 +1482,20 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } // Paper end - add close param @@ -11425,12 +11877,11 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 + // Folia - move into saveLevelData } -- private void saveLevelData(boolean async) { // Paper - Write SavedData IO async -+ public void saveLevelData(boolean async) { // Paper - Write SavedData IO async // Folia - public +- private void saveLevelData(boolean flush) { ++ public void saveLevelData(boolean flush) { // Folia - public if (this.dragonFight != null) { this.serverLevelData.setEndDragonFightData(this.dragonFight.saveData()); // CraftBukkit } - + // Folia start - moved into saveLevelData + ServerLevel worldserver1 = this; + @@ -11438,11 +11889,10 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 + this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save(this.registryAccess())); + this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); + // Folia end - moved into saveLevelData -+ - this.getChunkSource().getDataStorage().save(async); // Paper - Write SavedData IO async - } -@@ -1448,6 +1587,19 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + DimensionDataStorage worldpersistentdata = this.getChunkSource().getDataStorage(); + +@@ -1496,6 +1557,19 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe return list; } @@ -11462,7 +11912,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 @Nullable public ServerPlayer getRandomPlayer() { List list = this.getPlayers(LivingEntity::isAlive); -@@ -1532,8 +1684,8 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1580,8 +1654,8 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } else { if (entity instanceof net.minecraft.world.entity.item.ItemEntity itemEntity && itemEntity.getItem().isEmpty()) return false; // Paper - Prevent empty items from being added // Paper start - capture all item additions to the world @@ -11473,7 +11923,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 return true; } // Paper end - capture all item additions to the world -@@ -1684,21 +1836,22 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1750,21 +1824,22 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @Override public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) { @@ -11499,7 +11949,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 while (iterator.hasNext()) { // CraftBukkit start - fix SPIGOT-6362 -@@ -1721,7 +1874,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1787,7 +1862,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } try { @@ -11508,7 +11958,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 iterator = list.iterator(); while (iterator.hasNext()) { -@@ -1730,7 +1883,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1796,7 +1871,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe navigationabstract1.recomputePath(); } } finally { @@ -11517,45 +11967,52 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } } -@@ -1739,23 +1892,23 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1805,29 +1880,29 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @Override - public void updateNeighborsAt(BlockPos pos, Block sourceBlock) { + public void updateNeighborsAt(BlockPos pos, Block block) { - if (captureBlockStates) { return; } // Paper - Cancel all physics during placement -- this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, (Direction) null); + if (this.getCurrentWorldData().captureBlockStates) { return; } // Paper - Cancel all physics during placement // Folia - region threading -+ this.getCurrentWorldData().neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, (Direction) null); // Folia - region threading + this.updateNeighborsAt(pos, block, ExperimentalRedstoneUtils.initialOrientation(this, (Direction) null, (Direction) null)); } @Override - public void updateNeighborsAtExceptFromFacing(BlockPos pos, Block sourceBlock, Direction direction) { -- this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, direction); -+ this.getCurrentWorldData().neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, direction); // Folia - region threading + public void updateNeighborsAt(BlockPos pos, Block sourceBlock, @Nullable Orientation orientation) { +- if (captureBlockStates) { return; } // Paper - Cancel all physics during placement +- this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, (Direction) null, orientation); ++ if (this.getCurrentWorldData().captureBlockStates) { return; } // Paper - Cancel all physics during placement // Folia - region threading ++ this.getCurrentWorldData().neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, (Direction) null, orientation); // Folia - region threading } @Override - public void neighborChanged(BlockPos pos, Block sourceBlock, BlockPos sourcePos) { -- this.neighborUpdater.neighborChanged(pos, sourceBlock, sourcePos); -+ this.getCurrentWorldData().neighborUpdater.neighborChanged(pos, sourceBlock, sourcePos); // Folia - region threading + public void updateNeighborsAtExceptFromFacing(BlockPos pos, Block sourceBlock, Direction direction, @Nullable Orientation orientation) { +- this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, direction, orientation); ++ this.getCurrentWorldData().neighborUpdater.updateNeighborsAtExceptFromFacing(pos, sourceBlock, direction, orientation); // Folia - region threading } @Override - public void neighborChanged(BlockState state, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) { -- this.neighborUpdater.neighborChanged(state, pos, sourceBlock, sourcePos, notify); -+ this.getCurrentWorldData().neighborUpdater.neighborChanged(state, pos, sourceBlock, sourcePos, notify); // Folia - region threading + public void neighborChanged(BlockPos pos, Block sourceBlock, @Nullable Orientation orientation) { +- this.neighborUpdater.neighborChanged(pos, sourceBlock, orientation); ++ this.getCurrentWorldData().neighborUpdater.neighborChanged(pos, sourceBlock, orientation); // Folia - region threading } @Override -@@ -1788,7 +1941,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - explosion.clearToBlow(); + public void neighborChanged(BlockState state, BlockPos pos, Block sourceBlock, @Nullable Orientation orientation, boolean notify) { +- this.neighborUpdater.neighborChanged(state, pos, sourceBlock, orientation, notify); ++ this.getCurrentWorldData().neighborUpdater.neighborChanged(state, pos, sourceBlock, orientation, notify); // Folia - region threading + } + + @Override +@@ -1897,7 +1972,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } - + // CraftBukkit end + ParticleOptions particleparam2 = serverexplosion.isSmall() ? particleparam : particleparam1; - Iterator iterator = this.players.iterator(); + Iterator iterator = this.getLocalPlayers().iterator(); // Folia - region thraeding while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); -@@ -1803,25 +1956,28 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1918,25 +1993,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @Override public void blockEvent(BlockPos pos, Block block, int type, int data) { @@ -11590,7 +12047,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } private boolean doBlockEvent(BlockEventData event) { -@@ -1832,12 +1988,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1947,12 +2025,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @Override public LevelTicks getBlockTicks() { @@ -11605,7 +12062,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } @Nonnull -@@ -1861,7 +2017,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -1976,7 +2054,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public int sendParticles(ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { // Paper start - Particle API @@ -11614,7 +12071,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } public int sendParticles(List receivers, @Nullable ServerPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) { // Paper end - Particle API -@@ -1914,7 +2070,14 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2029,7 +2107,14 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public Entity getEntityOrPart(int id) { Entity entity = (Entity) this.getEntities().get(id); @@ -11630,23 +12087,23 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } @Nullable -@@ -1969,6 +2132,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2084,6 +2169,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // Paper start - Call missing map initialize event and set id final DimensionDataStorage storage = this.getServer().overworld().getDataStorage(); + synchronized (storage.cache) { // Folia - region threading - final net.minecraft.world.level.saveddata.SavedData existing = storage.cache.get(id.key()); - if (existing == null && !storage.cache.containsKey(id.key())) { - final MapItemSavedData worldmap = (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), id.key()); -@@ -1983,6 +2147,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + final Optional cacheEntry = storage.cache.get(id.key()); + if (cacheEntry == null) { // Cache did not contain, try to load and may init + final MapItemSavedData worldmap = storage.get(MapItemSavedData.factory(), id.key()); // get populates the cache +@@ -2103,6 +2189,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } - return existing instanceof MapItemSavedData data ? data : null; + return null; + } // Folia - region threading // Paper end - Call missing map initialize event and set id } -@@ -2032,6 +2197,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2152,6 +2239,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } public boolean setChunkForced(int x, int z, boolean forced) { @@ -11654,7 +12111,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 ForcedChunksSavedData forcedchunk = (ForcedChunksSavedData) this.getDataStorage().computeIfAbsent(ForcedChunksSavedData.factory(), "chunks"); ChunkPos chunkcoordintpair = new ChunkPos(x, z); long k = chunkcoordintpair.toLong(); -@@ -2040,7 +2206,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2160,7 +2248,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe if (forced) { flag1 = forcedchunk.getChunks().add(k); if (flag1) { @@ -11663,7 +12120,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } } else { flag1 = forcedchunk.getChunks().remove(k); -@@ -2068,13 +2234,18 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2188,13 +2276,18 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe BlockPos blockposition1 = pos.immutable(); optional.ifPresent((holder) -> { @@ -11685,7 +12142,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 // Paper start - Remove stale POIs if (optional.isEmpty() && this.getPoiManager().exists(blockposition1, poiType -> true)) { this.getPoiManager().remove(blockposition1); -@@ -2082,7 +2253,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2202,7 +2295,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // Paper end - Remove stale POIs this.getPoiManager().add(blockposition1, holder); DebugPackets.sendPoiAddedPacket(this, blockposition1); @@ -11699,7 +12156,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 }); } } -@@ -2129,7 +2305,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2249,7 +2347,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe BufferedWriter bufferedwriter = Files.newBufferedWriter(path.resolve("stats.txt")); try { @@ -11708,7 +12165,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 NaturalSpawner.SpawnState spawnercreature_d = this.getChunkSource().getLastSpawnState(); if (spawnercreature_d != null) { -@@ -2143,7 +2319,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2263,7 +2361,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } bufferedwriter.write(String.format(Locale.ROOT, "entities: %s\n", this.moonrise$getEntityLookup().getDebugInfo())); // Paper - rewrite chunk system @@ -11717,7 +12174,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 bufferedwriter.write(String.format(Locale.ROOT, "block_ticks: %d\n", this.getBlockTicks().count())); bufferedwriter.write(String.format(Locale.ROOT, "fluid_ticks: %d\n", this.getFluidTicks().count())); bufferedwriter.write("distance_manager: " + playerchunkmap.getDistanceManager().getDebugStatus() + "\n"); -@@ -2289,7 +2465,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2409,7 +2507,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe private void dumpBlockEntityTickers(Writer writer) throws IOException { CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("type").build(writer); @@ -11726,7 +12183,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 while (iterator.hasNext()) { TickingBlockEntity tickingblockentity = (TickingBlockEntity) iterator.next(); -@@ -2302,7 +2478,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2422,7 +2520,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @VisibleForTesting public void clearBlockEvents(BoundingBox box) { @@ -11735,7 +12192,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 return box.isInside(blockactiondata.pos()); }); } -@@ -2311,7 +2487,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2431,7 +2529,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public void blockUpdated(BlockPos pos, Block block) { if (!this.isDebug()) { // CraftBukkit start @@ -11744,7 +12201,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 return; } // CraftBukkit end -@@ -2354,9 +2530,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2474,9 +2572,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @VisibleForTesting public String getWatchdogStats() { @@ -11755,7 +12212,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } private static String getTypeCount(Iterable items, Function classifier) { -@@ -2406,17 +2580,18 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2526,17 +2622,18 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } public void startTickingChunk(LevelChunk chunk) { @@ -11779,7 +12236,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } @Override -@@ -2436,7 +2611,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2556,7 +2653,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe return this.moonrise$getAnyChunkIfLoaded(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkX(chunkPos), ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(chunkPos)) != null; // Paper - rewrite chunk system } @@ -11788,16 +12245,16 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 // Paper start - rewrite chunk system final ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder chunkHolder = this.moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(chunkPos); // isTicking implies the chunk is loaded, and the chunk is loaded now implies the entities are loaded -@@ -2496,7 +2671,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2651,7 +2748,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // Paper start - optimize redstone (Alternate Current) @Override public alternate.current.wire.WireHandler getWireHandler() { - return wireHandler; -+ return this.getCurrentWorldData().wireHandler; // Folia - region threading - move to regionised data ++ return this.getCurrentWorldData().wireHandler; // Folia - region threading } // Paper end - optimize redstone (Alternate Current) -@@ -2507,16 +2682,16 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2662,16 +2759,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public void onCreated(Entity entity) {} public void onDestroyed(Entity entity) { @@ -11815,9 +12272,9 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 - ServerLevel.this.entityTickList.remove(entity); + ServerLevel.this.getCurrentWorldData().removeEntityTickingEntity(entity); // Folia - region threading // Paper start - Reset pearls when they stop being ticked - if (paperConfig().fixes.disableUnloadedChunkEnderpearlExploit && entity instanceof net.minecraft.world.entity.projectile.ThrownEnderpearl pearl) { + if (ServerLevel.this.paperConfig().fixes.disableUnloadedChunkEnderpearlExploit && ServerLevel.this.paperConfig().misc.legacyEnderPearlBehavior && entity instanceof net.minecraft.world.entity.projectile.ThrownEnderpearl pearl) { pearl.cachedOwner = null; -@@ -2527,6 +2702,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2682,6 +2779,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public void onTrackingStart(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot @@ -11825,7 +12282,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true if (entity instanceof ServerPlayer entityplayer) { ServerLevel.this.players.add(entityplayer); -@@ -2540,7 +2716,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2695,7 +2793,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")); } @@ -11834,7 +12291,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } if (entity instanceof EnderDragon entityenderdragon) { -@@ -2550,7 +2726,9 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2705,7 +2803,9 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe for (int j = 0; j < i; ++j) { EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; @@ -11844,7 +12301,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } } -@@ -2572,16 +2750,24 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2727,16 +2827,24 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public void onTrackingEnd(Entity entity) { org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot @@ -11870,7 +12327,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 map.carriedByPlayers.remove( (Player) entity ); for ( Iterator iter = (Iterator) map.carriedBy.iterator(); iter.hasNext(); ) { -@@ -2591,6 +2777,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2746,6 +2854,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe iter.remove(); } } @@ -11878,7 +12335,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } } } ); -@@ -2621,7 +2808,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2776,7 +2885,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")); } @@ -11887,7 +12344,7 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 } if (entity instanceof EnderDragon entityenderdragon) { -@@ -2631,13 +2818,16 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -2786,13 +2895,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe for (int j = 0; j < i; ++j) { EnderDragonPart entitycomplexpart = aentitycomplexpart[j]; @@ -11902,30 +12359,22 @@ index f9abf63e12ea930275121b470e4e4906cff0fc12..f03f968d1526fbcff1ae87376370ba59 entity.valid = false; + // Folia - region threading - TODO THIS SHIT if (!(entity instanceof ServerPlayer)) { - for (ServerPlayer player : ServerLevel.this.players) { + for (ServerPlayer player : ServerLevel.this.server.getPlayerList().players) { // Paper - call onEntityRemove for all online players player.getBukkitEntity().onEntityRemove(entity); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb031063da 100644 +index 5a8f396d47577f087abb415c972fd4f51e50faba..f2884eefe00a35e19c83e069f65490dff95144a8 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -15,6 +15,7 @@ import java.util.Objects; - import java.util.Optional; - import java.util.OptionalInt; - import java.util.Set; -+import java.util.function.Consumer; - import java.util.stream.Collectors; - import javax.annotation.Nullable; - import net.minecraft.ChatFormatting; -@@ -203,7 +204,7 @@ import org.bukkit.inventory.MainHand; +@@ -221,7 +221,7 @@ import org.bukkit.inventory.MainHand; public class ServerPlayer extends net.minecraft.world.entity.player.Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system private static final Logger LOGGER = LogUtils.getLogger(); - public long lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving -+ public long lastSave = Long.MIN_VALUE; // Paper // Folia - threaded regions - changed to nanoTime ++ public static final long LAST_SAVE_ABSENT = Long.MIN_VALUE; public long lastSave = LAST_SAVE_ABSENT; // Paper // Folia - threaded regions - changed to nanoTime private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; private static final int FLY_STAT_RECORDING_SPEED = 25; -@@ -483,8 +484,153 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -543,8 +543,152 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple } // CraftBukkit end @@ -11956,7 +12405,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + } + + private static void completeSpawn(ServerLevel world, BlockPos selected, -+ ca.spottedleaf.concurrentutil.completable.Completable toComplete) { ++ ca.spottedleaf.concurrentutil.completable.CallbackCompletable toComplete) { + toComplete.complete(io.papermc.paper.util.MCUtil.toLocation(world, Vec3.atBottomCenterOf(selected), world.levelData.getSpawnAngle(), 0.0f)); + } + @@ -11964,14 +12413,14 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + // try hard to find, so that we don't attempt another chunk load + for (int dz = -SPAWN_RADIUS_SELECTION_SEARCH; dz <= SPAWN_RADIUS_SELECTION_SEARCH; ++dz) { + for (int dx = -SPAWN_RADIUS_SELECTION_SEARCH; dx <= SPAWN_RADIUS_SELECTION_SEARCH; ++dx) { -+ BlockPos inChunk = PlayerRespawnLogic.getOverworldRespawnPos(world, selected.getX(), selected.getZ()); ++ BlockPos inChunk = PlayerRespawnLogic.getOverworldRespawnPos(world, selected.getX() + dx, selected.getZ() + dz); + if (inChunk == null) { + continue; + } + + AABB checkVolume = player.getBoundingBoxAt((double)inChunk.getX() + 0.5, (double)inChunk.getY(), (double)inChunk.getZ() + 0.5); + -+ if (!world.noCollision(player, checkVolume)) { ++ if (!player.noCollisionNoLiquid(world, checkVolume)) { + continue; + } + @@ -11984,7 +12433,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + + // rets false when another attempt is required + private static boolean trySpawnOrSchedule(ServerLevel world, ServerPlayer player, RandomSource random, int[] attemptCount, int maxAttempts, -+ ca.spottedleaf.concurrentutil.completable.Completable toComplete) { ++ ca.spottedleaf.concurrentutil.completable.CallbackCompletable toComplete) { + ++attemptCount[0]; + + BlockPos rough = getRandomSpawn(world, random); @@ -11996,9 +12445,8 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + int maxZ = (rough.getZ() + (SPAWN_RADIUS_SELECTION_SEARCH + 2)) >> 4; + + // we could short circuit this check, but it would possibly recurse. Then, it could end up causing a stack overflow -+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(world, minX, minZ, maxX, maxZ) || !world.isAreaLoaded(minX, minZ, maxX, maxZ)) { -+ world.moonrise$loadChunksAsync(minX, maxX, minZ, maxZ, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(world, minX, minZ, maxX, maxZ) || !world.moonrise$areChunksLoaded(minX, minZ, maxX, maxZ)) { ++ world.moonrise$loadChunksAsync(minX, maxX, minZ, maxZ, ca.spottedleaf.concurrentutil.util.Priority.HIGHER, + (unused) -> { + BlockPos selected = findSpawnAround(world, player, rough); + if (selected == null) { @@ -12024,7 +12472,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + } + + private static void selectSpawn(ServerLevel world, ServerPlayer player, RandomSource random, int[] attemptCount, int maxAttempts, -+ ca.spottedleaf.concurrentutil.completable.Completable toComplete) { ++ ca.spottedleaf.concurrentutil.completable.CallbackCompletable toComplete) { + do { + if (attemptCount[0] >= maxAttempts) { + BlockPos sharedSpawn = world.getSharedSpawnPos(); @@ -12035,7 +12483,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + // this call requires to return a location with loaded chunks, so we need to schedule a load here + ca.spottedleaf.moonrise.common.util.ChunkSystem.scheduleChunkLoad( + world, selected.getX() >> 4, selected.getZ() >> 4, net.minecraft.world.level.chunk.status.ChunkStatus.FULL, -+ true, ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, ++ true, ca.spottedleaf.concurrentutil.util.Priority.HIGHER, + (unused) -> { + completeSpawn(world, selected, toComplete); + } @@ -12045,20 +12493,20 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + } while (!trySpawnOrSchedule(world, player, random, attemptCount, maxAttempts, toComplete)); + } + -+ public static void fudgeSpawnLocation(ServerLevel world, ServerPlayer player, ca.spottedleaf.concurrentutil.completable.Completable toComplete) { // Folia - region threading ++ public static void fudgeSpawnLocation(ServerLevel world, ServerPlayer player, ca.spottedleaf.concurrentutil.completable.CallbackCompletable toComplete) { // Folia - region threading + BlockPos blockposition = world.getSharedSpawnPos(); + + if (world.dimensionType().hasSkyLight() && world.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit + selectSpawn(world, player, player.random, new int[1], 500, toComplete); + } else { + world.loadChunksForMoveAsync(player.getBoundingBoxAt(blockposition.getX() + 0.5, blockposition.getY(), blockposition.getZ() + 0.5), -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, ++ ca.spottedleaf.concurrentutil.util.Priority.HIGHER, + (c) -> { + BlockPos ret = blockposition; -+ while (!world.noCollision(player, player.getBoundingBoxAt(ret.getX() + 0.5, ret.getY(), ret.getZ() + 0.5)) && ret.getY() < (double) (world.getMaxBuildHeight() - 1)) { // Paper - make sure this loads chunks, we default to NOT loading now ++ while (!player.noCollisionNoLiquid(world, player.getBoundingBoxAt(ret.getX() + 0.5, ret.getY(), ret.getZ() + 0.5)) && ret.getY() < (double)world.getMaxY()) { + ret = ret.above(); + } -+ while (world.noCollision(player, player.getBoundingBoxAt(ret.getX() + 0.5, ret.getY() - 1, ret.getZ() + 0.5)) && ret.getY() > (double) (world.getMaxBuildHeight() + 1)) { // Paper - make sure this loads chunks, we default to NOT loading now ++ while (player.noCollisionNoLiquid(world, player.getBoundingBoxAt(ret.getX() + 0.5, ret.getY() - 1, ret.getZ() + 0.5)) && ret.getY() > (double)(world.getMinY() + 1)) { + ret = ret.below(); + } + toComplete.complete(io.papermc.paper.util.MCUtil.toLocation(world, Vec3.atBottomCenterOf(ret), world.levelData.getSpawnAngle(), 0.0f)); @@ -12079,29 +12527,37 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb AABB axisalignedbb = this.getDimensions(Pose.STANDING).makeBoundingBox(Vec3.ZERO); BlockPos blockposition1 = basePos; -@@ -1320,6 +1466,334 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -885,11 +1029,18 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple + + if (worldserver != null) { + Entity entity = EntityType.loadEntityRecursive(nbttagcompound, worldserver, EntitySpawnReason.LOAD, (entity1) -> { +- return !worldserver.addWithUUID(entity1) ? null : entity1; ++ return entity1; // Folia - region threading - delay world add + }); + + if (entity != null) { +- ServerPlayer.placeEnderPearlTicket(worldserver, entity.chunkPosition()); ++ // Folia start - region threading ++ io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue( ++ worldserver, entity.chunkPosition().x, entity.chunkPosition().z, () -> { ++ worldserver.addFreshEntityWithPassengers(entity); ++ ServerPlayer.placeEnderPearlTicket(worldserver, entity.chunkPosition()); ++ } ++ ); ++ // Folia end - region threading + } else { + ServerPlayer.LOGGER.warn("Failed to spawn player ender pearl in level ({}), skipping", optional1.get()); + } +@@ -1581,6 +1732,323 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple } + // Folia start - region threading + /** + * Teleport flag indicating that the player is to be respawned, expected to only be used -+ * internally for {@link #respawn(Consumer, PlayerRespawnEvent.RespawnReason)} ++ * internally for {@link #respawn(java.util.function.Consumer, PlayerRespawnEvent.RespawnReason)} + */ + public static final long TELEPORT_FLAGS_PLAYER_RESPAWN = Long.MIN_VALUE >>> 0; -+ /** -+ * Teleport flag indicating the player should be placed at the highest y-value that -+ * provides no collisions for the player's bounding box. Note that this setting -+ * does not imply {@link Entity#TELEPORT_FLAG_LOAD_CHUNK}, so it may -+ * sync load chunks unless the load chunk flag is provided. -+ */ -+ public static final long TELEPORT_FLAGS_AVOID_SUFFOCATION = Long.MIN_VALUE >>> 1; -+ -+ private void avoidSuffocation() { -+ while (!this.level().noCollision(this, this.getBoundingBox()) && this.getY() < (double)this.level().getMaxBuildHeight()) { -+ this.setPos(this.getX(), this.getY() + 1.0D, this.getZ()); -+ } -+ } + + public void exitEndCredits() { + if (!this.wonGame) { @@ -12156,8 +12612,8 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + float respawnAngle = this.getRespawnAngle(); + boolean isRespawnForced = this.isRespawnForced(); + -+ ca.spottedleaf.concurrentutil.completable.Completable spawnPosComplete = -+ new ca.spottedleaf.concurrentutil.completable.Completable<>(); ++ ca.spottedleaf.concurrentutil.completable.CallbackCompletable spawnPosComplete = ++ new ca.spottedleaf.concurrentutil.completable.CallbackCompletable<>(); + boolean[] usedRespawnAnchor = new boolean[1]; + + // set up post spawn location logic @@ -12175,7 +12631,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + // use the load chunk flag just in case the spawn loc isn't loaded, and to ensure the chunks + // stay loaded for a bit with the teleport ticket + ((CraftWorld)spawnLoc.getWorld()).getHandle(), -+ TELEPORT_FLAG_LOAD_CHUNK | TELEPORT_FLAGS_PLAYER_RESPAWN | TELEPORT_FLAGS_AVOID_SUFFOCATION, ++ TELEPORT_FLAG_LOAD_CHUNK | TELEPORT_FLAGS_PLAYER_RESPAWN, + passengerTree, // note: we expect this to just be the player, no passengers + (entity) -> { + // now the player is in the world, and can receive sound @@ -12207,10 +12663,10 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + // give at least 1 radius of loaded chunks so that we do not sync load anything + int radiusBlocks = 16; + respawnWorld.moonrise$loadChunksAsync(respawnPos, radiusBlocks, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, ++ ca.spottedleaf.concurrentutil.util.Priority.HIGHER, + (chunks) -> { + ServerPlayer.RespawnPosAngle spawnPos = ServerPlayer.findRespawnAndUseSpawnBlock( -+ respawnWorld, respawnPos, respawnAngle, isRespawnForced, alive ++ respawnWorld, respawnPos, respawnAngle, isRespawnForced, !alive + ).orElse(null); + if (spawnPos == null) { + // no spawn @@ -12257,7 +12713,12 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + if (velocity != null) { + this.setDeltaMovement(velocity); + } -+ this.connection.internalTeleport(pos.x, pos.y, pos.z, this.getYRot(), this.getXRot(), java.util.Collections.emptySet()); ++ this.connection.internalTeleport( ++ new net.minecraft.world.entity.PositionMoveRotation( ++ pos, this.getDeltaMovement(), this.getYRot(), this.getXRot() ++ ), ++ java.util.Collections.emptySet() ++ ); + this.connection.resetPosition(); + this.resetStoredPositions(); + } @@ -12289,14 +12750,12 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + // must be manually added to connections + this.serverLevel().getCurrentWorldData().connections.add(this.connection.connection); + -+ if ((teleportFlags & TELEPORT_FLAGS_AVOID_SUFFOCATION) != 0L && treeNode.passengers == null && treeNode.parent == null) { -+ this.avoidSuffocation(); -+ } -+ + // required to set up the pending teleport stuff to the client, and to actually update + // the player's position clientside + this.connection.internalTeleport( -+ this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot(), ++ new net.minecraft.world.entity.PositionMoveRotation( ++ this.position(), this.getDeltaMovement(), this.getYRot(), this.getXRot() ++ ), + java.util.Collections.emptySet() + ); + this.connection.resetPosition(); @@ -12333,6 +12792,7 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + this.experienceProgress, this.totalExperience, this.experienceLevel + )); + ++ playerlist.sendActivePlayerEffects(this); + playerlist.sendLevelInfo(this, destination); + playerlist.sendPlayerPermissionLevel(this); + @@ -12343,14 +12803,12 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + // must be manually added to connections + this.serverLevel().getCurrentWorldData().connections.add(this.connection.connection); + -+ if ((teleportFlags & TELEPORT_FLAGS_AVOID_SUFFOCATION) != 0L && treeNode.passengers == null && treeNode.parent == null) { -+ this.avoidSuffocation(); -+ } -+ + // required to set up the pending teleport stuff to the client, and to actually update + // the player's position clientside + this.connection.internalTeleport( -+ this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot(), ++ new net.minecraft.world.entity.PositionMoveRotation( ++ this.position(), this.getDeltaMovement(), this.getYRot(), this.getXRot() ++ ), + java.util.Collections.emptySet() + ); + this.connection.resetPosition(); @@ -12363,9 +12821,9 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + this.setHealth(this.getHealth()); + playerlist.sendAllPlayerInfo(this); + this.onUpdateAbilities(); -+ for (MobEffectInstance mobEffect : this.getActiveEffects()) { ++ /*for (MobEffectInstance mobEffect : this.getActiveEffects()) { + this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), mobEffect, false)); -+ } ++ }*/ // handled by sendActivePlayerEffects + + // Paper start - Reset shield blocking on dimension change + if (this.isBlocking()) { @@ -12413,8 +12871,8 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb + @Nullable @Override - public Entity changeDimension(DimensionTransition teleportTarget) { -@@ -2369,6 +2843,12 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple + public ServerPlayer teleport(TeleportTransition teleportTarget) { +@@ -2625,6 +3093,12 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple public void setCamera(@Nullable Entity entity) { Entity entity1 = this.getCamera(); @@ -12427,7 +12885,21 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb this.camera = (Entity) (entity == null ? this : entity); if (entity1 != this.camera) { // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity -@@ -2922,7 +3402,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -3118,11 +3592,11 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple + } + + public void registerEnderPearl(ThrownEnderpearl enderPearl) { +- this.enderPearls.add(enderPearl); ++ //this.enderPearls.add(enderPearl); // Folia - region threading - do not track ender pearls + } + + public void deregisterEnderPearl(ThrownEnderpearl enderPearl) { +- this.enderPearls.remove(enderPearl); ++ //this.enderPearls.remove(enderPearl); // Folia - region threading - do not track ender pearls + } + + public Set getEnderPearls() { +@@ -3281,7 +3755,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple this.experienceLevel = this.newLevel; this.totalExperience = this.newTotalExp; this.experienceProgress = 0; @@ -12437,10 +12909,10 @@ index c396580a9cfd86ff261bed439bb4662ae88010b5..00b3c3c60f67d129058a888b7bd5e7fb this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.DEATH); this.effectsDirty = true; diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -index ee9e4521079137d7b72194e8789810e7a89b8e75..3669dbb613570feb953178389e098f0eb1376d47 100644 +index a96f859a5d0c6ec692d4627a69f3c9ee49199dbc..ad8da6726b4113068b200426ab1ac1e24a061942 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java -@@ -133,7 +133,7 @@ public class ServerPlayerGameMode { +@@ -131,7 +131,7 @@ public class ServerPlayerGameMode { BlockState iblockdata; if (this.hasDelayedDestroy) { @@ -12449,7 +12921,7 @@ index ee9e4521079137d7b72194e8789810e7a89b8e75..3669dbb613570feb953178389e098f0e if (iblockdata == null || iblockdata.isAir()) { // Paper - Don't allow digging into unloaded chunks this.hasDelayedDestroy = false; } else { -@@ -146,7 +146,7 @@ public class ServerPlayerGameMode { +@@ -144,7 +144,7 @@ public class ServerPlayerGameMode { } } else if (this.isDestroyingBlock) { // Paper start - Don't allow digging into unloaded chunks; don't want to do same logic as above, return instead @@ -12458,7 +12930,7 @@ index ee9e4521079137d7b72194e8789810e7a89b8e75..3669dbb613570feb953178389e098f0e if (iblockdata == null) { this.isDestroyingBlock = false; return; -@@ -424,7 +424,7 @@ public class ServerPlayerGameMode { +@@ -422,7 +422,7 @@ public class ServerPlayerGameMode { } else { // CraftBukkit start org.bukkit.block.BlockState state = bblock.getState(); @@ -12467,7 +12939,7 @@ index ee9e4521079137d7b72194e8789810e7a89b8e75..3669dbb613570feb953178389e098f0e // CraftBukkit end BlockState iblockdata1 = block.playerWillDestroy(this.level, pos, iblockdata, this.player); boolean flag = this.level.removeBlock(pos, false); -@@ -452,8 +452,8 @@ public class ServerPlayerGameMode { +@@ -450,8 +450,8 @@ public class ServerPlayerGameMode { // return true; // CraftBukkit } // CraftBukkit start @@ -12479,10 +12951,10 @@ index ee9e4521079137d7b72194e8789810e7a89b8e75..3669dbb613570feb953178389e098f0e org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - capture all item additions to the world } diff --git a/src/main/java/net/minecraft/server/level/TicketType.java b/src/main/java/net/minecraft/server/level/TicketType.java -index f56e5c0f53f9b52a9247b9be9265b949494fc924..765cd1eedda2e9aa928db4ac3b0776d154126fe3 100644 +index e701f57ac8b0efdf739389f9be7a255220bb3e21..acf6287da9a44796c0ba48297d682b9d2488bfd9 100644 --- a/src/main/java/net/minecraft/server/level/TicketType.java +++ b/src/main/java/net/minecraft/server/level/TicketType.java -@@ -25,6 +25,14 @@ public class TicketType { +@@ -26,6 +26,14 @@ public class TicketType { public static final TicketType UNKNOWN = TicketType.create("unknown", Comparator.comparingLong(ChunkPos::toLong), 1); public static final TicketType PLUGIN = TicketType.create("plugin", (a, b) -> 0); // CraftBukkit public static final TicketType PLUGIN_TICKET = TicketType.create("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // CraftBukkit @@ -12498,7 +12970,7 @@ index f56e5c0f53f9b52a9247b9be9265b949494fc924..765cd1eedda2e9aa928db4ac3b0776d1 public static TicketType create(String name, Comparator argumentComparator) { return new TicketType<>(name, argumentComparator, 0L); diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java -index 5a8a33638ceb1d980ffc3e6dd86e7eb11dfd9375..67b45f2916fa061e7430c6f3987bdb25ede58c04 100644 +index e4b0dc3121101d54394a0c3a413dabf8103b2ea6..0026ec8a393d4348d36242d745e4eccf6327744c 100644 --- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java +++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java @@ -115,6 +115,14 @@ public class WorldGenRegion implements WorldGenLevel { @@ -12525,10 +12997,10 @@ index 5a8a33638ceb1d980ffc3e6dd86e7eb11dfd9375..67b45f2916fa061e7430c6f3987bdb25 public boolean isOldChunkAround(ChunkPos chunkPos, int checkRadius) { diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -index 7174f8c89a7cdcf40ff28f6636ecfb23b13ccdaa..ea99a4e39cdfb4eeebc299030f7768b9c684df4e 100644 +index b0bc66dc7248aae691dcab68b925b52a1695e63f..d01063b964a67ecff2998a9e02e7f37a9af88c84 100644 --- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -@@ -113,6 +113,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -114,6 +114,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack } @@ -12539,7 +13011,7 @@ index 7174f8c89a7cdcf40ff28f6636ecfb23b13ccdaa..ea99a4e39cdfb4eeebc299030f7768b9 @Override public void onDisconnect(DisconnectionDetails info) { // Paper start - Fix kick event leave message not being sent -@@ -120,10 +124,18 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -121,10 +125,18 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack } public void onDisconnect(DisconnectionDetails info, @Nullable net.kyori.adventure.text.Component quitMessage) { // Paper end - Fix kick event leave message not being sent @@ -12558,7 +13030,7 @@ index 7174f8c89a7cdcf40ff28f6636ecfb23b13ccdaa..ea99a4e39cdfb4eeebc299030f7768b9 } -@@ -347,24 +359,8 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -354,24 +366,8 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack if (this.processedDisconnect) { return; } @@ -12585,7 +13057,7 @@ index 7174f8c89a7cdcf40ff28f6636ecfb23b13ccdaa..ea99a4e39cdfb4eeebc299030f7768b9 return; } -@@ -397,7 +393,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -404,7 +400,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack Objects.requireNonNull(this.connection); // CraftBukkit - Don't wait @@ -12594,7 +13066,7 @@ index 7174f8c89a7cdcf40ff28f6636ecfb23b13ccdaa..ea99a4e39cdfb4eeebc299030f7768b9 } // Paper start - add proper async disconnect -@@ -410,18 +406,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -417,18 +413,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack } public void disconnectAsync(DisconnectionDetails disconnectionInfo, PlayerKickEvent.Cause cause) { @@ -12615,7 +13087,7 @@ index 7174f8c89a7cdcf40ff28f6636ecfb23b13ccdaa..ea99a4e39cdfb4eeebc299030f7768b9 // Paper end - add proper async disconnect diff --git a/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java -index 880e5c52746e9e3a9a1f42ec6461be54e3ee136c..34c7fbf154c42d07b3b317b13632243a81904e3c 100644 +index 880e5c52746e9e3a9a1f42ec6461be54e3ee136c..70665e5bea075ced6db7696efcffe502f81cffdf 100644 --- a/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java @@ -54,6 +54,7 @@ public class ServerConfigurationPacketListenerImpl extends ServerCommonPacketLis @@ -12636,7 +13108,7 @@ index 880e5c52746e9e3a9a1f42ec6461be54e3ee136c..34c7fbf154c42d07b3b317b13632243a + CommonListenerCookie clientData = this.createCookie(this.clientInformation); + org.apache.commons.lang3.mutable.MutableObject data = new org.apache.commons.lang3.mutable.MutableObject<>(); + org.apache.commons.lang3.mutable.MutableObject lastKnownName = new org.apache.commons.lang3.mutable.MutableObject<>(); -+ ca.spottedleaf.concurrentutil.completable.Completable toComplete = new ca.spottedleaf.concurrentutil.completable.Completable<>(); ++ ca.spottedleaf.concurrentutil.completable.CallbackCompletable toComplete = new ca.spottedleaf.concurrentutil.completable.CallbackCompletable<>(); + // note: need to call addWaiter before completion to ensure the callback is invoked synchronously + // the loadSpawnForNewPlayer function always completes the completable once the chunks were loaded, + // on the load callback for those chunks (so on the same region) @@ -12669,7 +13141,7 @@ index 880e5c52746e9e3a9a1f42ec6461be54e3ee136c..34c7fbf154c42d07b3b317b13632243a + loc + ); + }, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER ++ ca.spottedleaf.concurrentutil.util.Priority.HIGHER + ); + }); + this.switchToMain = true; @@ -12715,10 +13187,10 @@ index 3a9e25b436f366fffe08c3b0c1fce11ed42ee646..ae88c6e2635b1608383f8c74813d723f Collections.shuffle( this.connections ); } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe555e0583 100644 +index b5d5dbc50a7b8c40739a15f164ffd08fdc534f9c..e2e7369e9439906c6db0720e5a2bc0e9c58d5490 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -300,7 +300,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -310,7 +310,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl private final LastSeenMessagesValidator lastSeenMessages = new LastSeenMessagesValidator(20); private final MessageSignatureCache messageSignatureCache = MessageSignatureCache.createDefault(); private final FutureChain chatMessageChain; @@ -12727,7 +13199,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe private static final int MAX_SIGN_LINE_LENGTH = Integer.getInteger("Paper.maxSignLength", 80); // Paper - Limit client sign length public ServerGamePacketListenerImpl(MinecraftServer server, Connection connection, ServerPlayer player, CommonListenerCookie clientData) { -@@ -317,10 +317,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -327,10 +327,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } // CraftBukkit start - add fields and methods @@ -12741,7 +13213,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe private int dropCount = 0; private boolean hasMoved = false; -@@ -332,8 +332,21 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -342,8 +342,21 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl private boolean justTeleported = false; // CraftBukkit end @@ -12763,16 +13235,16 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe if (this.ackBlockChangesUpTo > -1) { this.send(new ClientboundBlockChangedAckPacket(this.ackBlockChangesUpTo)); this.ackBlockChangesUpTo = -1; -@@ -382,7 +395,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -392,7 +405,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.aboveGroundVehicleTickCount = 0; } - this.keepConnectionAlive(); + // Folia - region threading - moved to beginning of method - // CraftBukkit start - for (int spam; (spam = this.chatSpamTickCount.get()) > 0 && !this.chatSpamTickCount.compareAndSet(spam, spam - 1); ) ; - if (tabSpamLimiter.get() > 0) tabSpamLimiter.getAndDecrement(); // Paper - configurable tab spam limits -@@ -431,6 +444,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + this.chatSpamThrottler.tick(); + this.tabSpamThrottler.tick(); // Paper - configurable tab spam limits + this.recipeSpamPackets.tick(); // Paper - auto recipe limit +@@ -430,6 +443,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.lastGoodX = this.player.getX(); this.lastGoodY = this.player.getY(); this.lastGoodZ = this.player.getZ(); @@ -12792,7 +13264,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe } @Override -@@ -531,9 +557,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -536,9 +562,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // Paper end - fix large move vectors killing the server // CraftBukkit start - handle custom speeds and skipped ticks @@ -12805,7 +13277,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe ++this.receivedMovePacketCount; int i = this.receivedMovePacketCount - this.knownMovePacketCount; -@@ -607,7 +634,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -612,7 +639,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } entity.absMoveTo(d3, d4, d5, f, f1); @@ -12814,7 +13286,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe // Paper start - optimise out extra getCubes boolean teleportBack = flag2; // violating this is always a fail -@@ -620,11 +647,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -625,11 +652,19 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } if (teleportBack) { // Paper end - optimise out extra getCubes entity.absMoveTo(d0, d1, d2, f, f1); @@ -12835,7 +13307,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe // CraftBukkit start - fire PlayerMoveEvent Player player = this.getCraftPlayer(); if (!this.hasMoved) { -@@ -664,7 +699,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -669,7 +704,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // If the event is cancelled we move the player back to their old location. if (event.isCancelled()) { @@ -12844,7 +13316,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe return; } -@@ -672,7 +707,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -677,7 +712,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. // We only do this if the Event was not cancelled. if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { @@ -12853,7 +13325,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe return; } -@@ -828,7 +863,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -840,7 +875,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } // This needs to be on main @@ -12862,7 +13334,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe } else if (!completions.isEmpty()) { final com.mojang.brigadier.suggestion.SuggestionsBuilder builder0 = new com.mojang.brigadier.suggestion.SuggestionsBuilder(packet.getCommand(), stringreader.getTotalLength()); final com.mojang.brigadier.suggestion.SuggestionsBuilder builder = builder0.createOffset(builder0.getInput().lastIndexOf(' ') + 1); -@@ -1196,11 +1231,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1211,11 +1246,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } // Paper end - Book size limits // CraftBukkit start @@ -12876,7 +13348,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe // CraftBukkit end int i = packet.slot(); -@@ -1220,7 +1255,22 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1232,7 +1267,22 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.updateBookContents(list1, i); }; @@ -12900,7 +13372,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe } } -@@ -1368,9 +1418,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1380,9 +1430,10 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl int i = this.receivedMovePacketCount - this.knownMovePacketCount; // CraftBukkit start - handle custom speeds and skipped ticks @@ -12913,7 +13385,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe if (i > Math.max(this.allowedPlayerTicks, 5)) { ServerGamePacketListenerImpl.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", this.player.getName().getString(), i); -@@ -1562,7 +1613,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1574,7 +1625,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // If the event is cancelled we move the player back to their old location. if (event.isCancelled()) { @@ -12922,7 +13394,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe return; } -@@ -1570,7 +1621,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1582,7 +1633,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // there to avoid any 'Moved wrongly' or 'Moved too quickly' errors. // We only do this if the Event was not cancelled. if (!oldTo.equals(event.getTo()) && !event.isCancelled()) { @@ -12931,7 +13403,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe return; } -@@ -1814,9 +1865,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1828,9 +1879,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl if (!this.player.isSpectator()) { // limit how quickly items can be dropped // If the ticks aren't the same then the count starts from 0 and we update the lastDropTick. @@ -12943,7 +13415,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe } else { // Else we increment the drop count and check the amount. this.dropCount++; -@@ -1844,7 +1895,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1858,7 +1909,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl case ABORT_DESTROY_BLOCK: case STOP_DESTROY_BLOCK: // Paper start - Don't allow digging into unloaded chunks @@ -12952,7 +13424,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe this.player.connection.ackBlockChangesUpTo(packet.getSequence()); return; } -@@ -1927,7 +1978,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -1941,7 +1992,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // Paper end - improve distance check BlockPos blockposition = movingobjectpositionblock.getBlockPos(); @@ -12961,16 +13433,16 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe Vec3 vec3d1 = vec3d.subtract(Vec3.atCenterOf(blockposition)); double d0 = 1.0000001D; -@@ -2049,7 +2100,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2072,7 +2123,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl Entity entity = packet.getEntity(worldserver); if (entity != null) { -- this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.SPECTATE); // CraftBukkit +- this.player.teleportTo(worldserver, entity.getX(), entity.getY(), entity.getZ(), Set.of(), entity.getYRot(), entity.getXRot(), true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.SPECTATE); // CraftBukkit + io.papermc.paper.threadedregions.TeleportUtils.teleport(this.player, false, entity, null, null, Entity.TELEPORT_FLAG_LOAD_CHUNK, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.SPECTATE, null); // Folia - region threading return; } } -@@ -2084,7 +2135,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2107,7 +2158,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl } // CraftBukkit end ServerGamePacketListenerImpl.LOGGER.info("{} lost connection: {}", this.player.getName().getString(), info.reason().getString()); @@ -12979,7 +13451,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe super.onDisconnect(info, quitMessage); // Paper - Fix kick event leave message not being sent } -@@ -2093,6 +2144,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2116,6 +2167,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.removePlayerFromWorld(null); } @@ -12988,7 +13460,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe private void removePlayerFromWorld(@Nullable net.kyori.adventure.text.Component quitMessage) { // Paper end - Fix kick event leave message not being sent this.chatMessageChain.close(); -@@ -2105,6 +2158,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2128,6 +2181,8 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.player.disconnect(); // Paper start - Adventure quitMessage = quitMessage == null ? this.server.getPlayerList().remove(this.player) : this.server.getPlayerList().remove(this.player, quitMessage); // Paper - pass in quitMessage to fix kick message not being used @@ -12997,7 +13469,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe if ((quitMessage != null) && !quitMessage.equals(net.kyori.adventure.text.Component.empty())) { this.server.getPlayerList().broadcastSystemMessage(PaperAdventure.asVanilla(quitMessage), false); // Paper end -@@ -2361,7 +2416,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2384,7 +2439,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.player.resetLastActionTime(); // CraftBukkit start if (sync) { @@ -13006,7 +13478,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe } else { runnable.run(); } -@@ -2419,7 +2474,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2442,7 +2497,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl String originalFormat = event.getFormat(), originalMessage = event.getMessage(); this.cserver.getPluginManager().callEvent(event); @@ -13015,7 +13487,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe // Evil plugins still listening to deprecated event final PlayerChatEvent queueEvent = new PlayerChatEvent(player, event.getMessage(), event.getFormat(), event.getRecipients()); queueEvent.setCancelled(event.isCancelled()); -@@ -2517,6 +2572,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2540,6 +2595,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl if (s.isEmpty()) { ServerGamePacketListenerImpl.LOGGER.warn(this.player.getScoreboardName() + " tried to send an empty message"); } else if (this.getCraftPlayer().isConversing()) { @@ -13023,7 +13495,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe final String conversationInput = s; this.server.processQueue.add(new Runnable() { @Override -@@ -2752,8 +2808,25 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2773,8 +2829,25 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl // Spigot End public void switchToConfig() { @@ -13050,7 +13522,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe this.send(ClientboundStartConfigurationPacket.INSTANCE); this.connection.setupOutboundProtocol(ConfigurationProtocols.CLIENTBOUND); } -@@ -2779,7 +2852,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2800,7 +2873,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.player.resetLastActionTime(); this.player.setShiftKeyDown(packet.isUsingSecondaryAction()); @@ -13059,7 +13531,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe if (!worldserver.getWorldBorder().isWithinBounds(entity.blockPosition())) { return; } -@@ -2923,6 +2996,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -2947,6 +3020,12 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl switch (packetplayinclientcommand_enumclientcommand) { case PERFORM_RESPAWN: if (this.player.wonGame) { @@ -13071,8 +13543,8 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe + // Folia end - region threading this.player.wonGame = false; this.player = this.server.getPlayerList().respawn(this.player, true, Entity.RemovalReason.CHANGED_DIMENSION, RespawnReason.END_PORTAL); // CraftBukkit - CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD); -@@ -2931,6 +3010,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + this.resetPosition(); +@@ -2956,6 +3035,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl return; } @@ -13080,17 +13552,17 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe + if (true) { + this.player.respawn((ServerPlayer player) -> { + if (ServerGamePacketListenerImpl.this.server.isHardcore()) { -+ player.setGameMode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper - Expand PlayerGameModeChangeEvent -+ ((GameRules.BooleanValue) player.level().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, player.serverLevel()); // CraftBukkit - per-world ++ ServerGamePacketListenerImpl.this.player.setGameMode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper - Expand PlayerGameModeChangeEvent ++ ((GameRules.BooleanValue) ServerGamePacketListenerImpl.this.player.serverLevel().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS)).set(false, ServerGamePacketListenerImpl.this.player.serverLevel()); // CraftBukkit - per-world + } + }, org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.DEATH); + return; + } + // Folia end - region threading this.player = this.server.getPlayerList().respawn(this.player, false, Entity.RemovalReason.KILLED, RespawnReason.DEATH); // CraftBukkit + this.resetPosition(); if (this.server.isHardcore()) { - this.player.setGameMode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper - Expand PlayerGameModeChangeEvent -@@ -3483,7 +3573,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl +@@ -3538,7 +3628,18 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl this.filterTextPacket(list).thenAcceptAsync((list1) -> { this.updateSignText(packet, list1); @@ -13111,7 +13583,7 @@ index 064d52d4479727c6a32bf357be8da32d1760e7fc..18d9e92f2fdc2cb25229005ffc08bffe private void updateSignText(ServerboundSignUpdatePacket packet, List signText) { diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 40638b439966619e9c70a18a32abd95b2178fe9f..9451cccebf7acee3bd9f28f4f9d60412d1554ff4 100644 +index 033755682c61c889723c3669b5cff4de147f637e..7fdb9304de7cf1979d57e3fac32415d7c674609d 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -111,7 +111,11 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, @@ -13211,7 +13683,7 @@ index 653856d0b8dcf2baf4cc77a276f17c8cc1fa717e..3f5639f26f249ca10e03826231d087ab date1 = fallback; } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066101656e4 100644 +index 30de3d1a7792c38ae946f19cb0e14637919b5001..c681c814046e6993a9ff6fa3545c4748452c0fb2 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -134,10 +134,10 @@ public abstract class PlayerList { @@ -13297,7 +13769,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor - public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie clientData) { -+ public void loadSpawnForNewPlayer(final Connection connection, final ServerPlayer player, final CommonListenerCookie clientData, org.apache.commons.lang3.mutable.MutableObject data, org.apache.commons.lang3.mutable.MutableObject lastKnownName, ca.spottedleaf.concurrentutil.completable.Completable toComplete) { // Folia - region threading - rewrite login process ++ public void loadSpawnForNewPlayer(final Connection connection, final ServerPlayer player, final CommonListenerCookie clientData, org.apache.commons.lang3.mutable.MutableObject data, org.apache.commons.lang3.mutable.MutableObject lastKnownName, ca.spottedleaf.concurrentutil.completable.CallbackCompletable toComplete) { // Folia - region threading - rewrite login process player.isRealPlayer = true; // Paper player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed GameProfile gameprofile = player.getGameProfile(); @@ -13317,7 +13789,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 + } else { + worldserver1.loadChunksForMoveAsync( + player.getBoundingBox(), -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, ++ ca.spottedleaf.concurrentutil.util.Priority.HIGHER, + (c) -> { + toComplete.complete(io.papermc.paper.util.MCUtil.toLocation(worldserver1, player.position())); + } @@ -13357,7 +13829,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 connection.setupInboundProtocol(GameProtocols.SERVERBOUND_TEMPLATE.bind(RegistryFriendlyByteBuf.decorator(this.server.registryAccess())), playerconnection); GameRules gamerules = worldserver1.getGameRules(); -@@ -305,7 +387,7 @@ public abstract class PlayerList { +@@ -307,7 +389,7 @@ public abstract class PlayerList { this.sendPlayerPermissionLevel(player); player.getStats().markAllDirty(); player.getRecipeBook().sendInitialRecipeBook(player); @@ -13366,7 +13838,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 this.server.invalidateStatus(); MutableComponent ichatmutablecomponent; -@@ -347,7 +429,7 @@ public abstract class PlayerList { +@@ -350,7 +432,7 @@ public abstract class PlayerList { this.cserver.getPluginManager().callEvent(playerJoinEvent); if (!player.connection.isAcceptingMessages()) { @@ -13375,7 +13847,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 } final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); -@@ -362,8 +444,7 @@ public abstract class PlayerList { +@@ -365,8 +447,7 @@ public abstract class PlayerList { ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player final List onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join @@ -13385,7 +13857,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) { // Paper start - Add Listing API for Player -@@ -476,7 +557,7 @@ public abstract class PlayerList { +@@ -415,7 +496,7 @@ public abstract class PlayerList { // Paper start - Configurable player collision; Add to collideRule team if needed final net.minecraft.world.scores.Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard(); final PlayerTeam collideRuleTeam = scoreboard.getPlayerTeam(this.collideRuleTeamName); @@ -13394,7 +13866,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam); } // Paper end - Configurable player collision -@@ -569,7 +650,7 @@ public abstract class PlayerList { +@@ -518,7 +599,7 @@ public abstract class PlayerList { protected void save(ServerPlayer player) { if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit @@ -13403,7 +13875,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 this.playerIo.save(player); ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit -@@ -609,7 +690,7 @@ public abstract class PlayerList { +@@ -558,7 +639,7 @@ public abstract class PlayerList { // CraftBukkit end // Paper start - Configurable player collision; Remove from collideRule team if needed @@ -13412,16 +13884,16 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 final net.minecraft.world.scores.Scoreboard scoreBoard = this.server.getLevel(Level.OVERWORLD).getScoreboard(); final PlayerTeam team = scoreBoard.getPlayersTeam(this.collideRuleTeamName); if (entityplayer.getTeam() == team && team != null) { -@@ -649,7 +730,7 @@ public abstract class PlayerList { +@@ -612,7 +693,7 @@ public abstract class PlayerList { + } - entityplayer.unRide(); worldserver.removePlayerImmediately(entityplayer, Entity.RemovalReason.UNLOADED_WITH_PLAYER); - entityplayer.retireScheduler(); // Paper - Folia schedulers + // Folia - region threading - move to onDisconnect of common packet listener entityplayer.getAdvancements().stopListening(); this.players.remove(entityplayer); this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -668,8 +749,7 @@ public abstract class PlayerList { +@@ -631,8 +712,7 @@ public abstract class PlayerList { // CraftBukkit start // this.broadcastAll(new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID()))); ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(entityplayer.getUUID())); @@ -13431,7 +13903,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 if (entityplayer2.getBukkitEntity().canSee(entityplayer.getBukkitEntity())) { entityplayer2.connection.send(packet); -@@ -694,19 +774,12 @@ public abstract class PlayerList { +@@ -657,19 +737,12 @@ public abstract class PlayerList { ServerPlayer entityplayer; @@ -13453,7 +13925,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 } // Instead of kicking then returning, we need to store the kick reason -@@ -726,7 +799,7 @@ public abstract class PlayerList { +@@ -689,7 +762,7 @@ public abstract class PlayerList { ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned.reason", gameprofilebanentry.getReason()); if (gameprofilebanentry.getExpires() != null) { @@ -13462,7 +13934,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 } // return chatmessage; -@@ -739,14 +812,14 @@ public abstract class PlayerList { +@@ -702,14 +775,14 @@ public abstract class PlayerList { ichatmutablecomponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipbanentry.getReason()); if (ipbanentry.getExpires() != null) { @@ -13479,7 +13951,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 event.disallow(PlayerLoginEvent.Result.KICK_FULL, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(org.spigotmc.SpigotConfig.serverFullMessage)); // Spigot // Paper - Adventure } } -@@ -806,6 +879,11 @@ public abstract class PlayerList { +@@ -769,6 +842,11 @@ public abstract class PlayerList { } public ServerPlayer respawn(ServerPlayer entityplayer, boolean flag, Entity.RemovalReason entity_removalreason, RespawnReason reason, Location location) { @@ -13491,7 +13963,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 entityplayer.stopRiding(); // CraftBukkit this.players.remove(entityplayer); this.playersByName.remove(entityplayer.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot -@@ -980,10 +1058,10 @@ public abstract class PlayerList { +@@ -945,10 +1023,10 @@ public abstract class PlayerList { public void tick() { if (++this.sendAllPlayerInfoIn > 600) { // CraftBukkit start @@ -13505,7 +13977,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 @Override public boolean test(ServerPlayer input) { return target.getBukkitEntity().canSee(input.getBukkitEntity()); -@@ -1009,18 +1087,17 @@ public abstract class PlayerList { +@@ -974,18 +1052,17 @@ public abstract class PlayerList { // CraftBukkit start - add a world/entity limited version public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) { @@ -13528,7 +14000,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 } } -@@ -1064,8 +1141,7 @@ public abstract class PlayerList { +@@ -1029,8 +1106,7 @@ public abstract class PlayerList { if (scoreboardteam == null) { this.broadcastSystemMessage(message, false); } else { @@ -13538,7 +14010,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 if (entityplayer.getTeam() != scoreboardteam) { entityplayer.sendSystemMessage(message); -@@ -1076,10 +1152,12 @@ public abstract class PlayerList { +@@ -1041,10 +1117,12 @@ public abstract class PlayerList { } public String[] getPlayerNamesArray() { @@ -13554,7 +14026,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 } return astring; -@@ -1098,7 +1176,9 @@ public abstract class PlayerList { +@@ -1063,7 +1141,9 @@ public abstract class PlayerList { ServerPlayer entityplayer = this.getPlayer(profile.getId()); if (entityplayer != null) { @@ -13564,7 +14036,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 } } -@@ -1108,7 +1188,10 @@ public abstract class PlayerList { +@@ -1073,7 +1153,10 @@ public abstract class PlayerList { ServerPlayer entityplayer = this.getPlayer(profile.getId()); if (entityplayer != null) { @@ -13575,7 +14047,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 } } -@@ -1171,8 +1254,7 @@ public abstract class PlayerList { +@@ -1136,8 +1219,7 @@ public abstract class PlayerList { } public void broadcast(@Nullable net.minecraft.world.entity.player.Player player, double x, double y, double z, double distance, ResourceKey worldKey, Packet packet) { @@ -13585,34 +14057,27 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 // CraftBukkit start - Test if player receiving packet can see the source of the packet if (player != null && !entityplayer.getBukkitEntity().canSee(player.getBukkitEntity())) { -@@ -1202,12 +1284,21 @@ public abstract class PlayerList { +@@ -1166,10 +1248,15 @@ public abstract class PlayerList { + public void saveAll(int interval) { io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper int numSaved = 0; - long now = MinecraftServer.currentTick; - for (int i = 0; i < this.players.size(); ++i) { -- ServerPlayer entityplayer = this.players.get(i); -- if (interval == -1 || now - entityplayer.lastSave >= interval) { +- final ServerPlayer player = this.players.get(i); +- if (interval == -1 || now - player.lastSave >= interval) { + long now = System.nanoTime(); // Folia - region threading -+ int max = io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick(); // Folia - region threading + long timeInterval = (long)interval * io.papermc.paper.threadedregions.TickRegionScheduler.TIME_BETWEEN_TICKS; // Folia - region threading -+ for (ServerPlayer entityplayer : this.players) { // Folia start - region threading -+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entityplayer)) { ++ for (ServerPlayer player : this.players) { // Folia - region threading ++ // Folia start - region threading ++ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(player)) { + continue; + } + // Folia end - region threading -+ if (interval == -1 || now - entityplayer.lastSave >= timeInterval) { // Folia - region threading - this.save(entityplayer); -- if (interval != -1 && ++numSaved >= io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick()) { break; } -+ // Folia start - region threading -+ if (interval != -1 && max != -1 && ++numSaved >= max) { -+ break; -+ } -+ // Folia end - region threading ++ if (interval == -1 || now - player.lastSave >= timeInterval) { // Folia - region threading + this.save(player); + if (interval != -1 && ++numSaved >= io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick()) { break; } } - // Paper end - Incremental chunk and player saving - } -@@ -1326,6 +1417,20 @@ public abstract class PlayerList { +@@ -1290,6 +1377,20 @@ public abstract class PlayerList { } public void removeAll(boolean isRestarting) { @@ -13633,7 +14098,7 @@ index b0e8fe11e7f5d1fd803fa34187c9fa77245ad79b..45830e2f6b2f745430cb38e86678d066 // Paper end // CraftBukkit start - disconnect safely for (ServerPlayer player : this.players) { -@@ -1335,7 +1440,7 @@ public abstract class PlayerList { +@@ -1299,7 +1400,7 @@ public abstract class PlayerList { // CraftBukkit end // Paper start - Configurable player collision; Remove collideRule team if it exists @@ -13675,10 +14140,10 @@ index c038da20b76c0b7b1c18471b20be01e849d29f3a..87114cc9ce7489ff8e29e2d88ebb0d47 } } diff --git a/src/main/java/net/minecraft/util/SpawnUtil.java b/src/main/java/net/minecraft/util/SpawnUtil.java -index 5c8e36ea8287029b1789719c687bac1a2c4c3a69..db0fe7fa257842eacd250f4cae6f549b9a0a91c9 100644 +index 34c3bf85473b3ad89355ebc21b68c59b3c683b84..3704a5b541210936e1f6414f2b322d51faff7e2a 100644 --- a/src/main/java/net/minecraft/util/SpawnUtil.java +++ b/src/main/java/net/minecraft/util/SpawnUtil.java -@@ -58,7 +58,7 @@ public class SpawnUtil { +@@ -59,7 +59,7 @@ public class SpawnUtil { return Optional.of(t0); } @@ -13688,7 +14153,7 @@ index 5c8e36ea8287029b1789719c687bac1a2c4c3a69..db0fe7fa257842eacd250f4cae6f549b } } diff --git a/src/main/java/net/minecraft/world/RandomSequences.java b/src/main/java/net/minecraft/world/RandomSequences.java -index c83598bfaa6fc9a6041fd828eb3c8b46334461a4..f8bc3450c054b201b7105e51bbba254efe2c2341 100644 +index 75631d9368bfc4baec1631db4f7dbfcc2c6d8ac5..320e113db209881d5dd619c6056a19a18b988e4c 100644 --- a/src/main/java/net/minecraft/world/RandomSequences.java +++ b/src/main/java/net/minecraft/world/RandomSequences.java @@ -21,7 +21,7 @@ public class RandomSequences extends SavedData { @@ -13699,7 +14164,7 @@ index c83598bfaa6fc9a6041fd828eb3c8b46334461a4..f8bc3450c054b201b7105e51bbba254e + private final Map sequences = new java.util.concurrent.ConcurrentHashMap<>(); // Folia - region threading public static SavedData.Factory factory(long seed) { - return new SavedData.Factory<>(() -> new RandomSequences(seed), (nbt, registryLookup) -> load(seed, nbt), DataFixTypes.SAVED_DATA_RANDOM_SEQUENCES); + return new SavedData.Factory<>(() -> new RandomSequences(seed), (nbt, registries) -> load(seed, nbt), DataFixTypes.SAVED_DATA_RANDOM_SEQUENCES); @@ -114,61 +114,61 @@ public class RandomSequences extends SavedData { @Override public RandomSource fork() { @@ -13828,19 +14293,19 @@ index e9df8f8541b8a1b85c7d2925ff3cba813007a1ef..d3f2775a68121ca80ef55ea4c280a0c9 return blockToFallLocation(blockState); } else { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2ae995f3e 100644 +index a15546e433ebba6c0de01bdaaef201a3d99a87b5..ad358909318a7e52d43e9dfb5cc7e6aa5674b9fd 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -178,7 +178,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -186,7 +186,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + } // Paper start - Share random for entities to make them more random - public static RandomSource SHARED_RANDOM = new RandomRandomSource(); -- private static final class RandomRandomSource extends java.util.Random implements net.minecraft.world.level.levelgen.BitRandomSource { -+ public static final class RandomRandomSource extends java.util.Random implements net.minecraft.world.level.levelgen.BitRandomSource { // Folia - region threading - private boolean locked = false; - - @Override -@@ -251,7 +251,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +- public static RandomSource SHARED_RANDOM = new RandomRandomSource(); ++ public static RandomSource SHARED_RANDOM = io.papermc.paper.threadedregions.util.ThreadLocalRandomSource.INSTANCE; // Folia - region threading + // Paper start - replace random + private static final class RandomRandomSource extends ca.spottedleaf.moonrise.common.util.ThreadUnsafeRandom { + public RandomRandomSource() { +@@ -216,7 +216,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason public boolean collisionLoadChunks = false; // Paper @@ -13849,7 +14314,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 public CraftEntity getBukkitEntity() { if (this.bukkitEntity == null) { -@@ -382,7 +382,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -339,7 +339,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess private boolean hasGlowingTag; private final Set tags; private final double[] pistonDeltas; @@ -13858,7 +14323,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 private EntityDimensions dimensions; private float eyeHeight; public boolean isInPowderSnow; -@@ -549,6 +549,19 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -568,6 +568,19 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } } // Paper end - optimise entity tracker @@ -13878,7 +14343,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 public Entity(EntityType type, Level world) { this.id = Entity.ENTITY_COUNTER.incrementAndGet(); -@@ -696,8 +709,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -719,8 +732,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // due to interactions on the client. public void resendPossiblyDesyncedEntityData(net.minecraft.server.level.ServerPlayer player) { if (player.getBukkitEntity().canSee(this.getBukkitEntity())) { @@ -13888,7 +14353,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 if (tracker == null) { return; } -@@ -852,7 +864,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -883,7 +895,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public void postTick() { // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle if (!(this instanceof ServerPlayer) && this.isAlive()) { // Paper - don't attempt to teleport dead entities @@ -13897,27 +14362,27 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 } } // CraftBukkit end -@@ -872,7 +884,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - this.walkDistO = this.walkDist; - this.xRotO = this.getXRot(); - this.yRotO = this.getYRot(); +@@ -902,7 +914,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + --this.boardingCooldown; + } + - if (this instanceof ServerPlayer) this.handlePortal(); // CraftBukkit - // Moved up to postTick + //if (this instanceof ServerPlayer) this.handlePortal(); // CraftBukkit - // Moved up to postTick // Folia - region threading - ONLY allow in postTick() if (this.canSpawnSprintParticle()) { this.spawnSprintParticle(); } -@@ -1130,8 +1142,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1178,8 +1190,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } else { this.wasOnFire = this.isOnFire(); - if (movementType == MoverType.PISTON) { -- this.activatedTick = Math.max(this.activatedTick, MinecraftServer.currentTick + 20); // Paper -- this.activatedImmunityTick = Math.max(this.activatedImmunityTick, MinecraftServer.currentTick + 20); // Paper -+ this.activatedTick = Math.max(this.activatedTick, io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() + 20); // Paper -+ this.activatedImmunityTick = Math.max(this.activatedImmunityTick, io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() + 20); // Paper + if (type == MoverType.PISTON) { +- this.activatedTick = Math.max(this.activatedTick, MinecraftServer.currentTick + 20); // Paper - EAR 2 +- this.activatedImmunityTick = Math.max(this.activatedImmunityTick, MinecraftServer.currentTick + 20); // Paper - EAR 2 ++ this.activatedTick = Math.max(this.activatedTick, io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() + 20); // Paper - EAR 2 // Folia - region threading ++ this.activatedImmunityTick = Math.max(this.activatedImmunityTick, io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() + 20); // Paper - EAR 2 // Folia - region threading movement = this.limitPistonMovement(movement); if (movement.equals(Vec3.ZERO)) { return; -@@ -1423,7 +1435,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -1488,7 +1500,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess if (movement.lengthSqr() <= 1.0E-7D) { return movement; } else { @@ -13926,7 +14391,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 if (i != this.pistonDeltasGameTime) { Arrays.fill(this.pistonDeltas, 0.0D); -@@ -3126,7 +3138,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3294,7 +3306,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.passengers = ImmutableList.copyOf(list); } @@ -13935,7 +14400,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 } } -@@ -3174,7 +3186,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3342,7 +3354,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } entity.boardingCooldown = 60; @@ -13944,7 +14409,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 } return true; // CraftBukkit } -@@ -3257,7 +3269,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3429,7 +3441,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } } @@ -13953,26 +14418,26 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 Level world = this.level(); if (world instanceof ServerLevel worldserver) { -@@ -3266,23 +3278,21 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - if (this.portalProcess.processPortalTeleportation(worldserver, this, this.canUsePortal(false))) { - worldserver.getProfiler().push("portal"); +@@ -3440,23 +3452,21 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + + gameprofilerfiller.push("portal"); this.setPortalCooldown(); -- DimensionTransition dimensiontransition = this.portalProcess.getPortalDestination(worldserver, this); +- TeleportTransition teleporttransition = this.portalProcess.getPortalDestination(worldserver, this); - -- if (dimensiontransition != null) { -- ServerLevel worldserver1 = dimensiontransition.newLevel(); +- if (teleporttransition != null) { +- ServerLevel worldserver1 = teleporttransition.newLevel(); - -- if (this instanceof ServerPlayer || (worldserver1 != null && (worldserver1.dimension() == worldserver.dimension() || this.canChangeDimensions(worldserver, worldserver1)))) { // CraftBukkit - always call event for players -- this.changeDimension(dimensiontransition); +- if (this instanceof ServerPlayer || (worldserver1 != null && (worldserver1.dimension() == worldserver.dimension() || this.canTeleport(worldserver, worldserver1)))) { // CraftBukkit - always call event for players +- this.teleport(teleporttransition); - } + // Folia start - region threading + try { + return this.portalProcess.portalAsync(worldserver, this); + } finally { -+ worldserver.getProfiler().pop(); ++ gameprofilerfiller.pop(); } - -- worldserver.getProfiler().pop(); +- gameprofilerfiller.pop(); + // Folia end - region threading } else if (this.portalProcess.hasExpired()) { this.portalProcess = null; @@ -13985,7 +14450,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 } public int getDimensionChangingDelay() { -@@ -3423,6 +3433,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3597,6 +3607,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @Nullable public PlayerTeam getTeam() { @@ -13997,7 +14462,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 if (!this.level().paperConfig().scoreboards.allowNonPlayerEntitiesOnScoreboards && !(this instanceof Player)) { return null; } // Paper - Perf: Disable Scoreboards for non players by default return this.level().getScoreboard().getPlayersTeam(this.getScoreboardName()); } -@@ -3712,8 +3727,751 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3890,8 +3905,778 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.portalProcess = original.portalProcess; } @@ -14238,7 +14703,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + + if ((teleportFlags & TELEPORT_FLAG_LOAD_CHUNK) != 0L) { + destination.loadChunksForMoveAsync( -+ this.getBoundingBox(), ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER, ++ this.getBoundingBox(), ca.spottedleaf.concurrentutil.util.Priority.HIGHER, + (chunkList) -> { + for (net.minecraft.world.level.chunk.ChunkAccess chunk : chunkList) { + destination.chunkSource.addTicketAtLevel( @@ -14281,6 +14746,15 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + this.resetStoredPositions(); + } + ++ protected final void transform(TeleportTransition telpeort) { ++ PositionMoveRotation move = PositionMoveRotation.calculateAbsolute( ++ PositionMoveRotation.of(this), PositionMoveRotation.of(telpeort), telpeort.relatives() ++ ); ++ this.transform( ++ move.position(), Float.valueOf(move.yRot()), Float.valueOf(move.xRot()), move.deltaMovement() ++ ); ++ } ++ + protected void transform(Vec3 pos, Float yaw, Float pitch, Vec3 velocity) { + if (yaw != null) { + this.setYRot(yaw.floatValue()); @@ -14297,10 +14771,19 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + } + } + ++ protected final Entity transformForAsyncTeleport(TeleportTransition telpeort) { ++ PositionMoveRotation move = PositionMoveRotation.calculateAbsolute( ++ PositionMoveRotation.of(this), PositionMoveRotation.of(telpeort), telpeort.relatives() ++ ); ++ return this.transformForAsyncTeleport( ++ telpeort.newLevel(), telpeort.position(), Float.valueOf(move.yRot()), Float.valueOf(move.xRot()), move.deltaMovement() ++ ); ++ } ++ + protected Entity transformForAsyncTeleport(ServerLevel destination, Vec3 pos, Float yaw, Float pitch, Vec3 velocity) { + this.removeAfterChangingDimensions(); // remove before so that any CBEntity#getHandle call affects this entity before copying + -+ Entity copy = this.getType().create(destination); ++ Entity copy = this.getType().create(destination, EntitySpawnReason.DIMENSION_TRAVEL); + copy.restoreFrom(this); + copy.transform(pos, yaw, pitch, velocity); + // vanilla code used to call remove _after_ copying, and some stuff is required to be after copy - so add hook here @@ -14310,6 +14793,16 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + return copy; + } + ++ public final boolean teleportAsync(TeleportTransition teleportTarget, long teleportFlags, ++ java.util.function.Consumer teleportComplete) { ++ PositionMoveRotation move = PositionMoveRotation.calculateAbsolute(PositionMoveRotation.of(this), PositionMoveRotation.of(teleportTarget), teleportTarget.relatives()); ++ ++ return this.teleportAsync( ++ teleportTarget.newLevel(), move.position(), Float.valueOf(move.yRot()), Float.valueOf(move.xRot()), move.deltaMovement(), ++ teleportTarget.cause(), teleportFlags, teleportComplete ++ ); ++ } ++ + public final boolean teleportAsync(ServerLevel destination, Vec3 pos, Float yaw, Float pitch, Vec3 velocity, + org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause, long teleportFlags, + java.util.function.Consumer teleportComplete) { @@ -14446,7 +14939,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + // If we have to worry about whether the entity may not teleport, + // we need to first search, then report back, ... + protected void findOrCreatePortalAsync(ServerLevel origin, BlockPos originPortal, ServerLevel destination, PortalType type, -+ ca.spottedleaf.concurrentutil.completable.Completable portalInfoCompletable) { ++ ca.spottedleaf.concurrentutil.completable.CallbackCompletable portalInfoCompletable) { + switch (type) { + // end portal logic is quite simple, the spawn in the end is fixed and when returning to the overworld + // we just select the spawn position @@ -14456,16 +14949,16 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + // need to load chunks so we can create the platform + destination.moonrise$loadChunksAsync( + targetPos, 16, // load 16 blocks to be safe from block physics -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGH, ++ ca.spottedleaf.concurrentutil.util.Priority.HIGH, + (chunks) -> { + net.minecraft.world.level.levelgen.feature.EndPlatformFeature.createEndPlatform(destination, targetPos.below(), true, null); + + // the portal obsidian is placed at targetPos.y - 2, so if we want to place the entity + // on the obsidian, we need to spawn at targetPos.y - 1 + portalInfoCompletable.complete( -+ new net.minecraft.world.level.portal.DimensionTransition( ++ new net.minecraft.world.level.portal.TeleportTransition( + destination, Vec3.atBottomCenterOf(targetPos.below()), Vec3.ZERO, 90.0f, 0.0f, -+ DimensionTransition.PLAY_PORTAL_SOUND.then(DimensionTransition.PLACE_PORTAL_TICKET), ++ TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET), + org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL + ) + ); @@ -14476,15 +14969,15 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + // need to load chunk for heightmap + destination.moonrise$loadChunksAsync( + spawnPos, 0, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGH, ++ ca.spottedleaf.concurrentutil.util.Priority.HIGH, + (chunks) -> { + BlockPos adjustedSpawn = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, spawnPos); + + // done + portalInfoCompletable.complete( -+ new net.minecraft.world.level.portal.DimensionTransition( ++ new net.minecraft.world.level.portal.TeleportTransition( + destination, Vec3.atBottomCenterOf(adjustedSpawn), Vec3.ZERO, 90.0f, 0.0f, -+ DimensionTransition.PLAY_PORTAL_SOUND.then(DimensionTransition.PLACE_PORTAL_TICKET), ++ TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET), + org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_PORTAL + ) + ); @@ -14524,8 +15017,8 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + double dimensionScale = net.minecraft.world.level.dimension.DimensionType.getTeleportationScale(origin.dimensionType(), destination.dimensionType()); + BlockPos targetPos = destination.getWorldBorder().clampToBounds(this.getX() * dimensionScale, this.getY(), this.getZ() * dimensionScale); + -+ ca.spottedleaf.concurrentutil.completable.Completable portalFound -+ = new ca.spottedleaf.concurrentutil.completable.Completable<>(); ++ ca.spottedleaf.concurrentutil.completable.CallbackCompletable portalFound ++ = new ca.spottedleaf.concurrentutil.completable.CallbackCompletable<>(); + + // post portal find/create logic + portalFound.addWaiter( @@ -14533,9 +15026,9 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + // no portal could be created + if (portal == null) { + portalInfoCompletable.complete( -+ new DimensionTransition(destination, Vec3.atCenterOf(targetPos), Vec3.ZERO, ++ new TeleportTransition(destination, Vec3.atCenterOf(targetPos), Vec3.ZERO, + 90.0f, 0.0f, -+ DimensionTransition.PLAY_PORTAL_SOUND.then(DimensionTransition.PLACE_PORTAL_TICKET)) ++ TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET)) + ); + return; + } @@ -14547,8 +15040,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + portalInfoCompletable.complete( + net.minecraft.world.level.block.NetherPortalBlock.createDimensionTransition( + destination, portal, originalPortalDirection, relativePos, -+ Entity.this, Entity.this.getDeltaMovement(), Entity.this.getYRot(), Entity.this.getXRot(), -+ DimensionTransition.PLAY_PORTAL_SOUND.then(DimensionTransition.PLACE_PORTAL_TICKET) ++ Entity.this, TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET) + ) + ); + } @@ -14559,7 +15051,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + // add 32 so that the final search for a portal frame doesn't load any chunks + targetPos, portalSearchRadius + 32, + net.minecraft.world.level.chunk.status.ChunkStatus.EMPTY, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGH, ++ ca.spottedleaf.concurrentutil.util.Priority.HIGH, + (chunks) -> { + BlockUtil.FoundRectangle portal = + net.minecraft.world.level.block.NetherPortalBlock.findPortalAround(destination, targetPos, destinationBorder, portalSearchRadius); @@ -14581,7 +15073,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + // no portal found - create one + destination.moonrise$loadChunksAsync( + targetPos, portalCreateRadius + 32, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGH, ++ ca.spottedleaf.concurrentutil.util.Priority.HIGH, + (chunks2) -> { + // don't need the tickets anymore + // note: we expect removeTicketsAtLevel to add an unknown ticket for us automatically @@ -14637,7 +15129,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + } + } + this.getBukkitEntity(); // force bukkit entity to be created before TPing -+ if (!this.canTeleportAsync() || !this.canChangeDimensions(this.level(), to)) { ++ if (!this.canTeleportAsync()) { + return false; + } + if (considerPassengers) { @@ -14697,10 +15189,10 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + ServerLevel.PendingTeleport beforeFindDestination = new ServerLevel.PendingTeleport(passengerTree, initialPosition); + originWorld.pushPendingTeleport(beforeFindDestination); + -+ ca.spottedleaf.concurrentutil.completable.Completable portalInfoCompletable -+ = new ca.spottedleaf.concurrentutil.completable.Completable<>(); ++ ca.spottedleaf.concurrentutil.completable.CallbackCompletable portalInfoCompletable ++ = new ca.spottedleaf.concurrentutil.completable.CallbackCompletable<>(); + -+ portalInfoCompletable.addWaiter((DimensionTransition info, Throwable throwable) -> { ++ portalInfoCompletable.addWaiter((TeleportTransition info, Throwable throwable) -> { + if (!originWorld.removePendingTeleport(beforeFindDestination)) { + // the shutdown thread has placed us back into the origin world at the original position + // we just have to abandon this teleport to prevent duplication @@ -14711,9 +15203,9 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.MAX_TICKET_LEVEL, + teleportHoldId + ); -+ // adjust passenger tree to final pos ++ // adjust passenger tree to final pos/rot/speed + for (EntityTreeNode node : fullPassengerTree) { -+ node.root.transform(info.pos(), Float.valueOf(info.yRot()), Float.valueOf(info.xRot()), info.speed()); ++ node.root.transform(info); + } + + // place @@ -14721,8 +15213,8 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + originWorld, destination, Entity.TELEPORT_FLAG_LOAD_CHUNK | (takePassengers ? Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS : 0L), + passengerTree, + (Entity teleported) -> { -+ if (info.postDimensionTransition() != null) { -+ info.postDimensionTransition().onTransition(teleported); ++ if (info.postTeleportTransition() != null) { ++ info.postTeleportTransition().onTransition(teleported); + } + + if (teleportComplete != null) { @@ -14740,7 +15232,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 + // Folia end - region threading + @Nullable - public Entity changeDimension(DimensionTransition teleportTarget) { + public Entity teleport(TeleportTransition teleportTarget) { + // Folia start - region threading + if (true) { + throw new UnsupportedOperationException("Must use teleportAsync while in region threading"); @@ -14749,7 +15241,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 Level world = this.level(); // Paper start - Fix item duplication and teleport issues -@@ -3832,6 +4590,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4096,6 +4881,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } @@ -14762,7 +15254,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 protected void removeAfterChangingDimensions() { this.setRemoved(Entity.RemovalReason.CHANGED_DIMENSION, null); // CraftBukkit - add Bukkit remove cause if (this instanceof Leashable leashable && leashable.isLeashed()) { // Paper - only call if it is leashed -@@ -4703,7 +5467,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -5029,7 +5820,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } } // Paper end - Fix MC-4 @@ -14772,7 +15264,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 synchronized (this.posLock) { // Paper this.position = new Vec3(x, y, z); } // Paper -@@ -4724,7 +5489,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -5050,7 +5842,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess // Paper start - Block invalid positions and bounding box; don't allow desync of pos and AABB // hanging has its own special logic @@ -14781,7 +15273,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 this.setBoundingBox(this.makeBoundingBox()); } // Paper end - Block invalid positions and bounding box -@@ -4809,6 +5574,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -5133,6 +5925,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return this.removalReason != null; } @@ -14794,7 +15286,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 @Nullable public Entity.RemovalReason getRemovalReason() { return this.removalReason; -@@ -4831,6 +5602,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -5155,6 +5953,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit end final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers @@ -14804,7 +15296,7 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 if (this.removalReason == null) { this.removalReason = entity_removalreason; } -@@ -4853,6 +5627,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -5178,6 +5979,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.removalReason = null; } @@ -14816,10 +15308,10 @@ index 4b54d0ea31062972e68ee8fafe3cfaf68f65a5cd..4aefadd491f1c0c541d23fcaeaf03fd2 /** * Invoked only when the entity is truly removed from the server, never to be added to any world. diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 2aa6374cd4a96efd85899be8cd3172a8257bfe6b..551ad6757e76ec9c731488f0355d4950ad1b0bd4 100644 +index f36a075dbee2b96d01899e02460b1d8443e91749..77eab187d4d6e22e5f8722029107c5613a9a7300 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -265,7 +265,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -276,7 +276,7 @@ public abstract class LivingEntity extends Entity implements Attackable { private Optional lastClimbablePos; @Nullable private DamageSource lastDamageSource; @@ -14828,7 +15320,7 @@ index 2aa6374cd4a96efd85899be8cd3172a8257bfe6b..551ad6757e76ec9c731488f0355d4950 protected int autoSpinAttackTicks; protected float autoSpinAttackDmg; @Nullable -@@ -299,6 +299,21 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -310,6 +310,21 @@ public abstract class LivingEntity extends Entity implements Attackable { ++this.noActionTime; // Above all the floats } // Spigot end @@ -14850,7 +15342,7 @@ index 2aa6374cd4a96efd85899be8cd3172a8257bfe6b..551ad6757e76ec9c731488f0355d4950 protected LivingEntity(EntityType type, Level world) { super(type, world); -@@ -519,7 +534,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -535,7 +550,7 @@ public abstract class LivingEntity extends Entity implements Attackable { if (this.isDeadOrDying() && this.level().shouldTickDeath(this)) { this.tickDeath(); @@ -14859,7 +15351,7 @@ index 2aa6374cd4a96efd85899be8cd3172a8257bfe6b..551ad6757e76ec9c731488f0355d4950 if (this.lastHurtByPlayerTime > 0) { --this.lastHurtByPlayerTime; -@@ -609,11 +624,14 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -625,11 +640,14 @@ public abstract class LivingEntity extends Entity implements Attackable { return true; } @@ -14876,7 +15368,7 @@ index 2aa6374cd4a96efd85899be8cd3172a8257bfe6b..551ad6757e76ec9c731488f0355d4950 } } -@@ -866,9 +884,9 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -888,9 +906,9 @@ public abstract class LivingEntity extends Entity implements Attackable { } this.hurtTime = nbt.getShort("HurtTime"); @@ -14888,7 +15380,7 @@ index 2aa6374cd4a96efd85899be8cd3172a8257bfe6b..551ad6757e76ec9c731488f0355d4950 String s = nbt.getString("Team"); Scoreboard scoreboard = this.level().getScoreboard(); PlayerTeam scoreboardteam = scoreboard.getPlayerTeam(s); -@@ -1146,6 +1164,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1167,6 +1185,7 @@ public abstract class LivingEntity extends Entity implements Attackable { public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) { // Paper end - Don't fire sync event during generation // org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot // Paper - move to API @@ -14896,7 +15388,7 @@ index 2aa6374cd4a96efd85899be8cd3172a8257bfe6b..551ad6757e76ec9c731488f0355d4950 if (this.isTickingEffects) { this.effectsToProcess.add(new ProcessableEffect(mobeffect, cause)); return true; -@@ -1594,7 +1613,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1628,7 +1647,7 @@ public abstract class LivingEntity extends Entity implements Attackable { if (flag2) { this.lastDamageSource = source; @@ -14905,7 +15397,7 @@ index 2aa6374cd4a96efd85899be8cd3172a8257bfe6b..551ad6757e76ec9c731488f0355d4950 Iterator iterator = this.getActiveEffects().iterator(); while (iterator.hasNext()) { -@@ -1696,7 +1715,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1737,7 +1756,7 @@ public abstract class LivingEntity extends Entity implements Attackable { @Nullable public DamageSource getLastDamageSource() { @@ -14914,7 +15406,7 @@ index 2aa6374cd4a96efd85899be8cd3172a8257bfe6b..551ad6757e76ec9c731488f0355d4950 this.lastDamageSource = null; } -@@ -2451,7 +2470,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2549,7 +2568,7 @@ public abstract class LivingEntity extends Entity implements Attackable { @Nullable public LivingEntity getKillCredit() { @@ -14923,25 +15415,25 @@ index 2aa6374cd4a96efd85899be8cd3172a8257bfe6b..551ad6757e76ec9c731488f0355d4950 } public final float getMaxHealth() { -@@ -2529,7 +2548,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2626,7 +2645,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + } - this.hurt(this.damageSources().generic(), 0.0F); this.lastDamageSource = damageSource; - this.lastDamageStamp = this.level().getGameTime(); + this.lastDamageStamp = this.level().getRedstoneGameTime(); // Folia - region threading } @Override -@@ -3553,7 +3572,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3692,7 +3711,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.pushEntities(); - this.level().getProfiler().pop(); + gameprofilerfiller.pop(); // Paper start - Add EntityMoveEvent - if (((ServerLevel) this.level()).hasEntityMoveEvent && !(this instanceof net.minecraft.world.entity.player.Player)) { + if (((ServerLevel) this.level()).getCurrentWorldData().hasEntityMoveEvent && !(this instanceof net.minecraft.world.entity.player.Player)) { // Folia - region threading if (this.xo != this.getX() || this.yo != this.getY() || this.zo != this.getZ() || this.yRotO != this.getYRot() || this.xRotO != this.getXRot()) { Location from = new Location(this.level().getWorld(), this.xo, this.yo, this.zo, this.yRotO, this.xRotO); Location to = new Location(this.level().getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); -@@ -4252,7 +4271,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -4406,7 +4425,7 @@ public abstract class LivingEntity extends Entity implements Attackable { BlockPos blockposition = BlockPos.containing(d0, d1, d2); Level world = this.level(); @@ -14949,12 +15441,12 @@ index 2aa6374cd4a96efd85899be8cd3172a8257bfe6b..551ad6757e76ec9c731488f0355d4950 + if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((ServerLevel)world, blockposition) && world.hasChunkAt(blockposition)) { // Folia - region threading boolean flag2 = false; - while (!flag2 && blockposition.getY() > world.getMinBuildHeight()) { + while (!flag2 && blockposition.getY() > world.getMinY()) { diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index 763abeea3f14f15c27d600e0bdae44b387687bb4..1cb0029739a487d930e4f10371c82d3a03a46de4 100644 +index dbd321f3dc3cc80737830db63aed47a6935e8e89..bd2d62f73e4f1fa1e655012d04e104acca5db198 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java -@@ -148,6 +148,14 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -150,6 +150,14 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab public boolean aware = true; // CraftBukkit @@ -14969,7 +15461,7 @@ index 763abeea3f14f15c27d600e0bdae44b387687bb4..1cb0029739a487d930e4f10371c82d3a protected Mob(EntityType type, Level world) { super(type, world); this.handItems = NonNullList.withSize(2, ItemStack.EMPTY); -@@ -293,8 +301,20 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -296,8 +304,20 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab @Nullable @Override public LivingEntity getTarget() { @@ -14990,7 +15482,7 @@ index 763abeea3f14f15c27d600e0bdae44b387687bb4..1cb0029739a487d930e4f10371c82d3a @Nullable protected final LivingEntity getTargetFromBrain() { -@@ -307,7 +327,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -310,7 +330,7 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab } public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { @@ -14999,7 +15491,7 @@ index 763abeea3f14f15c27d600e0bdae44b387687bb4..1cb0029739a487d930e4f10371c82d3a if (fireEvent) { if (reason == EntityTargetEvent.TargetReason.UNKNOWN && this.getTarget() != null && entityliving == null) { reason = this.getTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED; -@@ -1788,16 +1808,22 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab +@@ -1776,16 +1796,22 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab this.goalSelector.removeAllGoals(predicate); } @@ -15026,7 +15518,7 @@ index 763abeea3f14f15c27d600e0bdae44b387687bb4..1cb0029739a487d930e4f10371c82d3a @Nullable @Override diff --git a/src/main/java/net/minecraft/world/entity/PortalProcessor.java b/src/main/java/net/minecraft/world/entity/PortalProcessor.java -index 45761c113116ae7417e6ae99069bff35dbccdf30..c55d795209222a34c349d6f59eea36186324825d 100644 +index b4a8249964786d484aa0767d0e73d71d2156f0e8..0ee15cb6cc2698c511b2ba274f976d32bb5fbf4c 100644 --- a/src/main/java/net/minecraft/world/entity/PortalProcessor.java +++ b/src/main/java/net/minecraft/world/entity/PortalProcessor.java @@ -33,6 +33,12 @@ public class PortalProcessor { @@ -15043,10 +15535,10 @@ index 45761c113116ae7417e6ae99069bff35dbccdf30..c55d795209222a34c349d6f59eea3618 return this.portal.getLocalTransition(); } diff --git a/src/main/java/net/minecraft/world/entity/TamableAnimal.java b/src/main/java/net/minecraft/world/entity/TamableAnimal.java -index 9aee0569447d351729c26eedbe24d5defe620162..ea5096b88a6ac06f59792f29bc8ae52a0ba40840 100644 +index 332ae836826270507110f1e0438aaa36d6e9deb5..ae6098741088f89a693e5aaedbf64d33dc74eb69 100644 --- a/src/main/java/net/minecraft/world/entity/TamableAnimal.java +++ b/src/main/java/net/minecraft/world/entity/TamableAnimal.java -@@ -270,6 +270,11 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity { +@@ -281,6 +281,11 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity { LivingEntity entityliving = this.getOwner(); if (entityliving != null) { @@ -15058,7 +15550,7 @@ index 9aee0569447d351729c26eedbe24d5defe620162..ea5096b88a6ac06f59792f29bc8ae52a this.teleportToAroundBlockPos(entityliving.blockPosition()); } -@@ -307,7 +312,22 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity { +@@ -318,7 +323,22 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity { return false; } Location to = event.getTo(); @@ -15135,10 +15627,10 @@ index 15d7be9ed4a973044dd4399db46aaa244730b836..df4cce1d3baef0ad386f5bc201663ae5 @Override diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java -index 62634bedd97c5be9ecce24ab0cff205715a68da8..e03e07752e335d694c52c8dd780e71528021f15c 100644 +index f73b559b8e60859020f762dab88b67b8c912bf8f..9ca11453b99febb14177ec2a5f50bb542c953166 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/GroundPathNavigation.java -@@ -42,6 +42,11 @@ public class GroundPathNavigation extends PathNavigation { +@@ -43,6 +43,11 @@ public class GroundPathNavigation extends PathNavigation { @Override public Path createPath(BlockPos target, @javax.annotation.Nullable Entity entity, int distance) { // Paper - EntityPathfindEvent @@ -15151,10 +15643,10 @@ index 62634bedd97c5be9ecce24ab0cff205715a68da8..e03e07752e335d694c52c8dd780e7152 .getChunkSource() .getChunkNow(SectionPos.blockToSectionCoord(target.getX()), SectionPos.blockToSectionCoord(target.getZ())); diff --git a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -index 2e9991e6b3c05584002744a2ee2579b1dba218b2..7873462c6146b7431011a2b73eb7414f61afbccf 100644 +index 48c0de870a5bbf647309e69361dfb10ab56c65ab..71885b8b3f491fbe644efef02aebdd8b9f03a10b 100644 --- a/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java +++ b/src/main/java/net/minecraft/world/entity/ai/navigation/PathNavigation.java -@@ -80,11 +80,11 @@ public abstract class PathNavigation { +@@ -96,11 +96,11 @@ public abstract class PathNavigation { } public void recomputePath() { @@ -15168,7 +15660,7 @@ index 2e9991e6b3c05584002744a2ee2579b1dba218b2..7873462c6146b7431011a2b73eb7414f this.hasDelayedRecomputation = false; } } else { -@@ -203,7 +203,7 @@ public abstract class PathNavigation { +@@ -220,7 +220,7 @@ public abstract class PathNavigation { public boolean moveTo(Entity entity, double speed) { // Paper start - Perf: Optimise pathfinding @@ -15177,7 +15669,7 @@ index 2e9991e6b3c05584002744a2ee2579b1dba218b2..7873462c6146b7431011a2b73eb7414f return false; } // Paper end - Perf: Optimise pathfinding -@@ -215,7 +215,7 @@ public abstract class PathNavigation { +@@ -232,7 +232,7 @@ public abstract class PathNavigation { return true; } else { this.pathfindFailures++; @@ -15186,21 +15678,34 @@ index 2e9991e6b3c05584002744a2ee2579b1dba218b2..7873462c6146b7431011a2b73eb7414f return false; } // Paper end - Perf: Optimise pathfinding +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +index e1ff702e56adef6c8a572b078b49de2143c4ce7e..6c9e9c4173e62fc69e6da2b0bc7e6cc886f39fbe 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +@@ -22,7 +22,7 @@ public class PlayerSensor extends Sensor { + + @Override + protected void doTick(ServerLevel world, LivingEntity entity) { +- List list = world.players() ++ List list = world.getLocalPlayers() // Folia - region threading + .stream() + .filter(EntitySelector.NO_SPECTATORS) + .filter(player -> entity.closerThan(player, this.getFollowDistance(entity))) diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/TemptingSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/TemptingSensor.java -index 4d5372b80b2b1906ecf5bf7e75df08b5d3792bfd..9ee62edd8f71244ea406f19cdd62fa5a94b85a3d 100644 +index 4090d98b264d13f76f93742bac7e895a5b0a72ea..4dd2dcb092ef6301d9986d4217d8ca647ec4565b 100644 --- a/src/main/java/net/minecraft/world/entity/ai/sensing/TemptingSensor.java +++ b/src/main/java/net/minecraft/world/entity/ai/sensing/TemptingSensor.java -@@ -38,7 +38,7 @@ public class TemptingSensor extends Sensor { - +@@ -39,7 +39,7 @@ public class TemptingSensor extends Sensor { protected void doTick(ServerLevel world, PathfinderMob entity) { Brain behaviorcontroller = entity.getBrain(); + TargetingConditions pathfindertargetcondition = TemptingSensor.TEMPT_TARGETING.copy().range((double) ((float) entity.getAttributeValue(Attributes.TEMPT_RANGE))); - Stream stream = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((entityplayer) -> { // CraftBukkit - decompile error + Stream stream = world.getLocalPlayers().stream().filter(EntitySelector.NO_SPECTATORS).filter((entityplayer) -> { // CraftBukkit - decompile error // Folia - region threading - return TemptingSensor.TEMPT_TARGETING.test(entity, entityplayer); - }).filter((entityplayer) -> { - return entity.closerThan(entityplayer, 10.0D); + return pathfindertargetcondition.test(world, entity, entityplayer); + }).filter(this::playerHoldingTemptation).filter((entityplayer) -> { + return !entity.hasPassenger((Entity) entityplayer); diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java -index 36dec6cd78a0990ba3c09a4a748c259ef5c0a2ff..a2bc957bd643b90595711270ab88382c957e24b6 100644 +index bd3f71c3eaa33258ff56062ea3a2099cef310b7a..326be10d31d0b546a325f4af97bb413910e79e31 100644 --- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java +++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java @@ -21,62 +21,66 @@ import org.slf4j.Logger; @@ -15324,7 +15829,7 @@ index 36dec6cd78a0990ba3c09a4a748c259ef5c0a2ff..a2bc957bd643b90595711270ab88382c try { entityzombie = new Zombie(world); + entityzombie.moveTo(vec3d.x, vec3d.y, vec3d.z, world.random.nextFloat() * 360.0F, 0.0F); // Folia - region threading - move up - entityzombie.finalizeSpawn(world, world.getCurrentDifficultyAt(entityzombie.blockPosition()), MobSpawnType.EVENT, (SpawnGroupData) null); + entityzombie.finalizeSpawn(world, world.getCurrentDifficultyAt(entityzombie.blockPosition()), EntitySpawnReason.EVENT, (SpawnGroupData) null); } catch (Exception exception) { VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception); @@ -121,7 +127,7 @@ public class VillageSiege implements CustomSpawner { @@ -15346,10 +15851,10 @@ index 36dec6cd78a0990ba3c09a4a748c259ef5c0a2ff..a2bc957bd643b90595711270ab88382c SIEGE_CAN_ACTIVATE, SIEGE_TONIGHT, SIEGE_DONE; diff --git a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -index a908bf1dc5e821dcf6981a8c21076fb0bdc6516d..1e7f11e5dda502fde6ca122f3edb2d2a161f3469 100644 +index 63a94b6068fdaef8bb26675c2927cb729ced1dac..f3f98e6276dda3bc4f290fc2d80569f7e1e7ef66 100644 --- a/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java +++ b/src/main/java/net/minecraft/world/entity/ai/village/poi/PoiManager.java -@@ -58,11 +58,13 @@ public class PoiManager extends SectionStorage implements ca.spotted +@@ -58,11 +58,13 @@ public class PoiManager extends SectionStorage im } private void updateDistanceTracking(long section) { @@ -15363,18 +15868,20 @@ index a908bf1dc5e821dcf6981a8c21076fb0bdc6516d..1e7f11e5dda502fde6ca122f3edb2d2a } @Override -@@ -359,8 +361,10 @@ public class PoiManager extends SectionStorage implements ca.spotted +@@ -345,10 +347,12 @@ public class PoiManager extends SectionStorage im } public int sectionsToVillage(SectionPos pos) { + synchronized (this.villageDistanceTracker) { // Folia - region threading - this.villageDistanceTracker.propagateUpdates(); // Paper - rewrite chunk system - return convertBetweenLevels(this.villageDistanceTracker.getLevel(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkSectionKey(pos))); // Paper - rewrite chunk system + // Paper start - rewrite chunk system + this.villageDistanceTracker.propagateUpdates(); + return convertBetweenLevels(this.villageDistanceTracker.getLevel(ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkSectionKey(pos))); + // Paper end - rewrite chunk system + } // Folia - region threading } boolean isVillageCenter(long pos) { -@@ -374,7 +378,9 @@ public class PoiManager extends SectionStorage implements ca.spotted +@@ -362,7 +366,9 @@ public class PoiManager extends SectionStorage im @Override public void tick(BooleanSupplier shouldKeepTicking) { @@ -15385,10 +15892,10 @@ index a908bf1dc5e821dcf6981a8c21076fb0bdc6516d..1e7f11e5dda502fde6ca122f3edb2d2a @Override diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java -index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..9fa53a54f2d39962aec8abe95d8311da0f7b40a6 100644 +index 42276acfeadec6e7aa9a91d3f446f4fedb04829d..aaa3e1e5fa2e34078500f20934e9709784353e70 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Bee.java +++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -1036,6 +1036,11 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -1095,6 +1095,11 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override public boolean canBeeUse() { @@ -15397,10 +15904,10 @@ index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..9fa53a54f2d39962aec8abe95d8311da + Bee.this.hivePos = null; + } + // Folia end - region threading - return Bee.this.hivePos != null && !Bee.this.hasRestriction() && Bee.this.wantsToEnterHive() && !this.hasReachedTarget(Bee.this.hivePos) && Bee.this.level().getBlockState(Bee.this.hivePos).is(BlockTags.BEEHIVES); + return Bee.this.hivePos != null && !Bee.this.isTooFarAway(Bee.this.hivePos) && !Bee.this.hasRestriction() && Bee.this.wantsToEnterHive() && !this.hasReachedTarget(Bee.this.hivePos) && Bee.this.level().getBlockState(Bee.this.hivePos).is(BlockTags.BEEHIVES); } -@@ -1152,6 +1157,11 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { +@@ -1208,6 +1213,11 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { @Override public boolean canBeeUse() { @@ -15409,68 +15916,67 @@ index 1b3978f4ea7e8491e0c0cb6de23c141f44fab414..9fa53a54f2d39962aec8abe95d8311da + Bee.this.savedFlowerPos = null; + } + // Folia end - region threading - return Bee.this.savedFlowerPos != null && !Bee.this.hasRestriction() && this.wantsToGoToKnownFlower() && Bee.this.isFlowerValid(Bee.this.savedFlowerPos) && !Bee.this.closerThan(Bee.this.savedFlowerPos, 2); + return Bee.this.savedFlowerPos != null && !Bee.this.hasRestriction() && this.wantsToGoToKnownFlower() && !Bee.this.closerThan(Bee.this.savedFlowerPos, 2); } diff --git a/src/main/java/net/minecraft/world/entity/animal/Cat.java b/src/main/java/net/minecraft/world/entity/animal/Cat.java -index 23d4dcc82115fd1a0a77565a0472304042d5f12d..c7cd84527887cf7280b802cc110a9352cf63b4b3 100644 +index 471d5727b964922d8e898be9e1d5c30f9d3bac97..665ee9dc2cb129ea67b2f3ec454a0fd99be237a4 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Cat.java +++ b/src/main/java/net/minecraft/world/entity/animal/Cat.java -@@ -357,7 +357,7 @@ public class Cat extends TamableAnimal implements VariantHolder type, Level world) { super(type, world); -@@ -155,10 +155,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { +@@ -157,10 +157,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { public void tick() { if (!this.level().isClientSide && this.isAlive() && this.isConverting()) { int i = this.getConversionProgress(); @@ -15558,7 +16064,7 @@ index e0dabbf6d7a87b8722769c78ef0d2ba4353ed2cb..90627c6a0c0e0f03a20cd32a7f15a0cf this.villagerConversionTime -= i; if (this.villagerConversionTime <= 0) { -@@ -167,7 +164,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { +@@ -169,7 +166,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder { } super.tick(); @@ -15568,7 +16074,7 @@ index e0dabbf6d7a87b8722769c78ef0d2ba4353ed2cb..90627c6a0c0e0f03a20cd32a7f15a0cf @Override diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -index d28ebcae036168dd65a5f3236d12ee416308c23f..4153d16c3fc6b16315b3822251e4f740cf7dbd98 100644 +index 5f656fc726a1dc5f42657095a2f2b7cf85b92d7c..8a907164cb1f8a51c46a3e6f578867545a83a73a 100644 --- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java +++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java @@ -224,10 +224,18 @@ public abstract class AbstractVillager extends AgeableMob implements InventoryCa @@ -15585,14 +16091,14 @@ index d28ebcae036168dd65a5f3236d12ee416308c23f..4153d16c3fc6b16315b3822251e4f740 + @Nullable @Override - public Entity changeDimension(DimensionTransition teleportTarget) { + public Entity teleport(TeleportTransition teleportTarget) { - this.stopTrading(); + this.preChangeDimension(); // Folia - region threading - move into preChangeDimension - return super.changeDimension(teleportTarget); + return super.teleport(teleportTarget); } diff --git a/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java b/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java -index e0e5046c84941a8d17e18c177f3daea9cb631940..61adcf62cb738d7dd5c785780824f64c56b82082 100644 +index b0236c7bf9441aa84d3795ffed05dd6099f29636..4a8214160946f94d8a2fa13785f205a324a32949 100644 --- a/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java +++ b/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java @@ -18,17 +18,18 @@ import net.minecraft.world.phys.AABB; @@ -15620,7 +16126,7 @@ index e0e5046c84941a8d17e18c177f3daea9cb631940..61adcf62cb738d7dd5c785780824f64c return 0; } else { diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java -index 7e1871401ec5e3e9a85232053490259f132aec0a..91728a992a29bc22e46a260750d5dd88e629bfd1 100644 +index b7a34f1c4d7b5ef3f7a843d152e33c839dcdedd5..d33dc470850acdc0cecfbad7f7990a9deb57edaf 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java +++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -204,7 +204,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler @@ -15628,11 +16134,11 @@ index 7e1871401ec5e3e9a85232053490259f132aec0a..91728a992a29bc22e46a260750d5dd88 brain.setDefaultActivity(Activity.IDLE); brain.setActiveActivityIfPossible(Activity.IDLE); - brain.updateActivityFromSchedule(this.level().getDayTime(), this.level().getGameTime()); -+ brain.updateActivityFromSchedule(this.level().getLevelData().getDayTime(), this.level().getLevelData().getGameTime()); // Folia - region threading ++ brain.updateActivityFromSchedule(this.level().getLevelData().getDayTime(), this.level().getLevelData().getGameTime()); // Folia - region threading - not in the world yet } @Override -@@ -724,6 +724,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -710,6 +710,8 @@ public class Villager extends AbstractVillager implements ReputationEventHandler ServerLevel worldserver = minecraftserver.getLevel(globalpos.dimension()); if (worldserver != null) { @@ -15641,7 +16147,7 @@ index 7e1871401ec5e3e9a85232053490259f132aec0a..91728a992a29bc22e46a260750d5dd88 PoiManager villageplace = worldserver.getPoiManager(); Optional> optional = villageplace.getType(globalpos.pos()); BiPredicate> bipredicate = (BiPredicate) Villager.POI_MEMORIES.get(pos); -@@ -732,6 +734,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler +@@ -718,6 +720,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler villageplace.release(globalpos.pos()); DebugPackets.sendPoiTicketCountPacket(worldserver, globalpos.pos()); } @@ -15650,7 +16156,7 @@ index 7e1871401ec5e3e9a85232053490259f132aec0a..91728a992a29bc22e46a260750d5dd88 } }); diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java -index c72b6ea5530e54fc373c701028e1c147cea34b59..6677b4cc23253a1b7dfbc2e12e666699bbadbdb4 100644 +index a728dcbf956f108f01c966c7531449a506a14a87..d8e5ef40b32dd2e8b5fb6f4a00a3d3faea6e66ba 100644 --- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java +++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java @@ -32,16 +32,14 @@ public class WanderingTraderSpawner implements CustomSpawner { @@ -15658,7 +16164,7 @@ index c72b6ea5530e54fc373c701028e1c147cea34b59..6677b4cc23253a1b7dfbc2e12e666699 private static final int SPAWN_ONE_IN_X_CHANCE = 10; private static final int NUMBER_OF_SPAWN_ATTEMPTS = 10; - private final RandomSource random = RandomSource.create(); -+ private final RandomSource random = new net.minecraft.world.entity.Entity.RandomRandomSource(); // Folia - region threading ++ private final RandomSource random = io.papermc.paper.threadedregions.util.ThreadLocalRandomSource.INSTANCE; // Folia - region threading private final ServerLevelData serverLevelData; - private int tickDelay; - private int spawnDelay; @@ -15743,10 +16249,10 @@ index c72b6ea5530e54fc373c701028e1c147cea34b59..6677b4cc23253a1b7dfbc2e12e666699 entityvillagertrader.setWanderTarget(blockposition1); entityvillagertrader.restrictTo(blockposition1, 16); diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 09bcbc0ae36e4e69fee87a7e0c49acf496117a39..b3377ed06d703f54e01ba174e5a06dc928cdff96 100644 +index 61d412c4f1ebd55661cc3f0260468e3ac0efe0bb..e00bcd424d500aa4b76d0fd88eb4b9558d3aece5 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1558,6 +1558,14 @@ public abstract class Player extends LivingEntity { +@@ -1515,6 +1515,14 @@ public abstract class Player extends LivingEntity { } @@ -15762,28 +16268,28 @@ index 09bcbc0ae36e4e69fee87a7e0c49acf496117a39..b3377ed06d703f54e01ba174e5a06dc9 return false; } diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -index 9ca29b3d4bf8bca5f51f3644e12fcbec2cb5d35e..b5edbd36a1114449fe5f9bf1018bff7988fa7262 100644 +index 571f0699772eecbe02d71845da82a142321f2142..0e579039508f4ab07ec41db3cff494cc31998dab 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java -@@ -187,6 +187,11 @@ public abstract class AbstractArrow extends Projectile { +@@ -196,6 +196,11 @@ public abstract class AbstractArrow extends Projectile { + @Override public void tick() { - super.tick(); + // Folia start - region threading - make sure entities do not move into regions they do not own + if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level(), this.position(), this.getDeltaMovement(), 1)) { + return; + } + // Folia end - region threading - make sure entities do not move into regions they do not own - boolean flag = this.isNoPhysics(); + boolean flag = !this.isNoPhysics(); Vec3 vec3d = this.getDeltaMovement(); - + BlockPos blockposition = this.blockPosition(); diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -index f79fc0ed58af2cf55e8642b6d7fc9e4f57d0ba20..f70905fde2591cbabf15d47ff3c87b6662b966d5 100644 +index a84dccc59f9dc5298b18f263dc779c30c9b7ddab..fb2bb11fb7a1a47f59d80a6148025ca865782a1e 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractHurtingProjectile.java -@@ -79,6 +79,11 @@ public abstract class AbstractHurtingProjectile extends Projectile { - this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause - } else { +@@ -93,6 +93,11 @@ public abstract class AbstractHurtingProjectile extends Projectile { + this.setPos(vec3d); + this.applyEffectsFromBlocks(); super.tick(); + // Folia start - region threading - make sure entities do not move into regions they do not own + if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level(), this.position(), this.getDeltaMovement(), 1)) { @@ -15794,10 +16300,10 @@ index f79fc0ed58af2cf55e8642b6d7fc9e4f57d0ba20..f70905fde2591cbabf15d47ff3c87b66 this.igniteForSeconds(1.0F); } diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -index 09d465947a5720e05c350d455c86002682104079..16bb8fedbfc1618a77c0967eaa0b234d0d82255b 100644 +index 8a4e7e1c0c4919d2ee34121c14f9665b9ad95273..e6dedd9e1421515459dfc156007ecff5cba1faa5 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java +++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -@@ -136,6 +136,11 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { +@@ -144,6 +144,11 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { }); } @@ -15810,19 +16316,19 @@ index 09d465947a5720e05c350d455c86002682104079..16bb8fedbfc1618a77c0967eaa0b234d if (this.attachedToEntity != null) { if (this.attachedToEntity.isFallFlying()) { diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -index 1223c5d23d0ea6aed068bdf0f5725e2ad49fc82c..cd058156c79223991c725882bc04426ad066af28 100644 +index 4daa69c6be6d48563e30343a7e40e4da9ec7e5ad..5d08d1ce4b908c13518b7ec845e364c290d9ac25 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java +++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java -@@ -106,7 +106,7 @@ public class FishingHook extends Projectile { +@@ -105,7 +105,7 @@ public class FishingHook extends Projectile { - public FishingHook(net.minecraft.world.entity.player.Player thrower, Level world, int luckBonus, int waitTimeReductionTicks) { + public FishingHook(net.minecraft.world.entity.player.Player thrower, Level world, int luckBonus, int waitTimeReductionTicks, ItemStack stack) { this(EntityType.FISHING_BOBBER, world, luckBonus, waitTimeReductionTicks); - this.setOwner(thrower); + //this.setOwner(thrower); // Folia - region threading - move this down after position so that thread-checks do not fail float f = thrower.getXRot(); float f1 = thrower.getYRot(); float f2 = Mth.cos(-f1 * 0.017453292F - 3.1415927F); -@@ -118,6 +118,7 @@ public class FishingHook extends Projectile { +@@ -117,6 +117,7 @@ public class FishingHook extends Projectile { double d2 = thrower.getZ() - (double) f2 * 0.3D; this.moveTo(d0, d1, d2, f1, f); @@ -15830,7 +16336,7 @@ index 1223c5d23d0ea6aed068bdf0f5725e2ad49fc82c..cd058156c79223991c725882bc04426a Vec3 vec3d = new Vec3((double) (-f3), (double) Mth.clamp(-(f5 / f4), -5.0F, 5.0F), (double) (-f2)); double d3 = vec3d.length(); -@@ -268,6 +269,11 @@ public class FishingHook extends Projectile { +@@ -273,6 +274,11 @@ public class FishingHook extends Projectile { } private boolean shouldStopFishing(net.minecraft.world.entity.player.Player player) { @@ -15842,7 +16348,7 @@ index 1223c5d23d0ea6aed068bdf0f5725e2ad49fc82c..cd058156c79223991c725882bc04426a ItemStack itemstack = player.getMainHandItem(); ItemStack itemstack1 = player.getOffhandItem(); boolean flag = itemstack.is(Items.FISHING_ROD); -@@ -631,10 +637,18 @@ public class FishingHook extends Projectile { +@@ -636,10 +642,18 @@ public class FishingHook extends Projectile { @Override public void remove(Entity.RemovalReason entity_removalreason, EntityRemoveEvent.Cause cause) { // CraftBukkit end @@ -15863,7 +16369,7 @@ index 1223c5d23d0ea6aed068bdf0f5725e2ad49fc82c..cd058156c79223991c725882bc04426a public void onClientRemoval() { this.updateOwnerInfo((FishingHook) null); diff --git a/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java b/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java -index 8575941fd238750c5d56843989a48bcbde2d8a88..185501a2daea0351281c578bff79dc506994e146 100644 +index 958ea103cc80da7366cc33dc385b76d4f5c809f2..40645ef84efb096646d7bf7cd8c445b981c15de6 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java +++ b/src/main/java/net/minecraft/world/entity/projectile/LlamaSpit.java @@ -41,6 +41,11 @@ public class LlamaSpit extends Projectile { @@ -15879,10 +16385,10 @@ index 8575941fd238750c5d56843989a48bcbde2d8a88..185501a2daea0351281c578bff79dc50 HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -index 10ade433c083851d9ea4797c6ec618db122229f9..0e831070fe7a9ac58de4b25b74a53b38334c695a 100644 +index 6c2d4d6f3a36ab452dfd3c33f66e54f152906639..522fa33311b433f8c0eff4cb10dd80128f3c96d7 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java -@@ -38,7 +38,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { +@@ -44,7 +44,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { @Nullable public UUID ownerUUID; @Nullable @@ -15891,7 +16397,7 @@ index 10ade433c083851d9ea4797c6ec618db122229f9..0e831070fe7a9ac58de4b25b74a53b38 public boolean leftOwner; public boolean hasBeenShot; @Nullable -@@ -55,7 +55,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { +@@ -61,7 +61,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { public void setOwner(@Nullable Entity entity) { if (entity != null) { this.ownerUUID = entity.getUUID(); @@ -15900,7 +16406,7 @@ index 10ade433c083851d9ea4797c6ec618db122229f9..0e831070fe7a9ac58de4b25b74a53b38 } // Paper start - Refresh ProjectileSource for projectiles else { -@@ -71,18 +71,29 @@ public abstract class Projectile extends Entity implements TraceableEntity { +@@ -77,22 +77,38 @@ public abstract class Projectile extends Entity implements TraceableEntity { if (fillCache) { this.getOwner(); } @@ -15930,37 +16436,45 @@ index 10ade433c083851d9ea4797c6ec618db122229f9..0e831070fe7a9ac58de4b25b74a53b38 this.refreshProjectileSource(false); // Paper - Refresh ProjectileSource for projectiles - return this.cachedOwner; + return this.cachedOwner.getHandleRaw(); // Folia - region threading + } else if (this.ownerUUID != null) { +- this.cachedOwner = this.findOwner(this.ownerUUID); ++ // Folia start - region threading ++ Entity ret = this.findOwner(this.ownerUUID); ++ if (ret != null) { ++ this.cachedOwner = ret.getBukkitEntity(); ++ } ++ // Folia end - region threading + this.refreshProjectileSource(false); // Paper - Refresh ProjectileSource for projectiles +- return this.cachedOwner; ++ return ret; // Folia - region threading } else { - if (this.ownerUUID != null) { - Level world = this.level(); -@@ -90,9 +101,14 @@ public abstract class Projectile extends Entity implements TraceableEntity { - if (world instanceof ServerLevel) { - ServerLevel worldserver = (ServerLevel) world; + return null; + } +@@ -144,7 +160,12 @@ public abstract class Projectile extends Entity implements TraceableEntity { + protected void setOwnerThroughUUID(UUID uuid) { + if (this.ownerUUID != uuid) { + this.ownerUUID = uuid; +- this.cachedOwner = this.findOwner(uuid); ++ // Folia start - region threading ++ Entity cachedOwner = this.findOwner(this.ownerUUID); ++ if (cachedOwner != null) { ++ this.cachedOwner = cachedOwner.getBukkitEntity(); ++ } ++ // Folia end - region threading + } -- this.cachedOwner = worldserver.getEntity(this.ownerUUID); -+ // Folia start - region threading -+ Entity ret = worldserver.getEntity(this.ownerUUID); -+ if (ret != null) { -+ this.cachedOwner = ret.getBukkitEntity(); -+ } -+ // Folia end - region threading - this.refreshProjectileSource(false); // Paper - Refresh ProjectileSource for projectiles -- return this.cachedOwner; -+ return ret; // Folia - region threading - } - } - -@@ -364,7 +380,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { - public boolean mayInteract(Level world, BlockPos pos) { + } +@@ -480,7 +501,7 @@ public abstract class Projectile extends Entity implements TraceableEntity { + public boolean mayInteract(ServerLevel world, BlockPos pos) { Entity entity = this.getOwner(); - return entity instanceof Player ? entity.mayInteract(world, pos) : entity == null || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); + return entity instanceof Player && ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(entity) ? entity.mayInteract(world, pos) : entity == null || world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); // Folia - region threading } - public boolean mayBreak(Level world) { + public boolean mayBreak(ServerLevel world) { diff --git a/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java b/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java -index 1711ad457e7d1233fd32edc3e9e3b9f1e3be9980..62c55a5ef3c6c46d3c7638fd2e726d15690d8a0b 100644 +index bb159ea4baf208aab6d6fcfbbddacd5b089b55c8..6a0c3e8e304f3861366e06345b20bd790d858e55 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java +++ b/src/main/java/net/minecraft/world/entity/projectile/SmallFireball.java @@ -29,7 +29,7 @@ public class SmallFireball extends Fireball { @@ -15968,36 +16482,37 @@ index 1711ad457e7d1233fd32edc3e9e3b9f1e3be9980..62c55a5ef3c6c46d3c7638fd2e726d15 super(EntityType.SMALL_FIREBALL, owner, velocity, world); // CraftBukkit start - if (this.getOwner() != null && this.getOwner() instanceof Mob) { -+ if (owner != null && owner instanceof Mob) { // Folia - region threading - this.isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); ++ if (owner != null && this.getOwner() instanceof Mob) { // Folia - region threading + this.isIncendiary = (world instanceof ServerLevel worldserver) && worldserver.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); } // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java -index bf4c1883a1257af89428d6580a177f3af3759ee7..38ff937ef3908d344dd43b8934854ea66eb7b733 100644 +index c309198d092fdae6bdcc5d773b7b707bab2738bd..ff53dfec183e7933e5ceda8bf5a88b179d8d8532 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java +++ b/src/main/java/net/minecraft/world/entity/projectile/ThrowableProjectile.java -@@ -43,6 +43,11 @@ public abstract class ThrowableProjectile extends Projectile { +@@ -46,6 +46,11 @@ public abstract class ThrowableProjectile extends Projectile { + @Override public void tick() { - super.tick(); + // Folia start - region threading - make sure entities do not move into regions they do not own + if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)this.level(), this.position(), this.getDeltaMovement(), 1)) { + return; + } + // Folia end - region threading - make sure entities do not move into regions they do not own - HitResult movingobjectposition = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity); - - if (movingobjectposition.getType() != HitResult.Type.MISS) { + this.handleFirstTickBubbleColumn(); + this.applyGravity(); + this.applyInertia(); diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -index 1aa5e57a4e6a4be60514d8808a2e6c973d93e798..dfee42d73853a87fb9bb0150e428582fe430536e 100644 +index bd2684528157f928460f2143dd71a48e11983123..3bd0f3ae53eaa22409152d7f41e511e76bdaa265 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java +++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -@@ -47,6 +47,76 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { +@@ -120,6 +120,81 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { entityHitResult.getEntity().hurt(this.damageSources().thrown(this, this.getOwner()), 0.0F); } + // Folia start - region threading + private static void attemptTeleport(Entity source, ServerLevel checkWorld, net.minecraft.world.phys.Vec3 to) { ++ final boolean onPortalCooldown = source.isOnPortalCooldown(); + // ignore retired callback, in those cases we do not want to teleport + source.getBukkitEntity().taskScheduler.schedule( + (Entity entity) -> { @@ -16009,7 +16524,11 @@ index 1aa5e57a4e6a4be60514d8808a2e6c973d93e798..dfee42d73853a87fb9bb0150e428582f + + // dismount from any vehicles, so we can teleport and to prevent desync + if (entity.isPassenger()) { -+ entity.stopRiding(); ++ entity.unRide(); ++ } ++ ++ if (onPortalCooldown) { ++ entity.setPortalCooldown(); + } + + entity.teleportAsync( @@ -16025,7 +16544,7 @@ index 1aa5e57a4e6a4be60514d8808a2e6c973d93e798..dfee42d73853a87fb9bb0150e428582f + + // endermite spawn chance + if (world.random.nextFloat() < 0.05F && world.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { -+ Endermite entityendermite = (Endermite) EntityType.ENDERMITE.create(world); ++ Endermite entityendermite = (Endermite) EntityType.ENDERMITE.create(world, EntitySpawnReason.TRIGGERED); + + if (entityendermite != null) { + float yRot = teleported.getYRot(); @@ -16051,7 +16570,7 @@ index 1aa5e57a4e6a4be60514d8808a2e6c973d93e798..dfee42d73853a87fb9bb0150e428582f + // damage player + teleported.resetFallDistance(); + player.resetCurrentImpulseContext(); -+ player.hurt(teleported.damageSources().fall().customEventDamager(teleported), 5.0F); // CraftBukkit // Paper - fix DamageSource API ++ player.hurtServer(player.serverLevel(), player.damageSources().enderPearl().customEventDamager(player), 5.0F); // CraftBukkit // Paper - fix DamageSource API + playSound(teleported.level(), to); + } else { + // reset fall damage so that if the entity was falling they do not instantly die @@ -16069,7 +16588,7 @@ index 1aa5e57a4e6a4be60514d8808a2e6c973d93e798..dfee42d73853a87fb9bb0150e428582f @Override protected void onHit(HitResult hitResult) { super.onHit(hitResult); -@@ -59,6 +129,20 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { +@@ -132,6 +207,20 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { if (world instanceof ServerLevel worldserver) { if (!this.isRemoved()) { @@ -16090,8 +16609,8 @@ index 1aa5e57a4e6a4be60514d8808a2e6c973d93e798..dfee42d73853a87fb9bb0150e428582f Entity entity = this.getOwner(); if (entity != null && ThrownEnderpearl.isAllowedToTeleportOwner(entity, worldserver)) { -@@ -135,7 +219,15 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { - +@@ -242,7 +331,15 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { + } } - private void playSound(Level world, Vec3 pos) { @@ -16108,7 +16627,7 @@ index 1aa5e57a4e6a4be60514d8808a2e6c973d93e798..dfee42d73853a87fb9bb0150e428582f } diff --git a/src/main/java/net/minecraft/world/entity/raid/Raid.java b/src/main/java/net/minecraft/world/entity/raid/Raid.java -index dcbef04bbaab988096bf416163264833e84d1967..e1987d1d6e5fd05e155c05dd1fdaf569e303d74a 100644 +index 11cf2d9def087b0898c828eaa21eb5f7b8811d5f..5ff4a4af7f166f5f977efe41263ca487fe1b270b 100644 --- a/src/main/java/net/minecraft/world/entity/raid/Raid.java +++ b/src/main/java/net/minecraft/world/entity/raid/Raid.java @@ -113,6 +113,13 @@ public class Raid { @@ -16134,7 +16653,7 @@ index dcbef04bbaab988096bf416163264833e84d1967..e1987d1d6e5fd05e155c05dd1fdaf569 }; } -@@ -550,7 +557,7 @@ public class Raid { +@@ -541,7 +548,7 @@ public class Raid { boolean flag = true; Collection collection = this.raidEvent.getPlayers(); long i = this.random.nextLong(); @@ -16144,10 +16663,10 @@ index dcbef04bbaab988096bf416163264833e84d1967..e1987d1d6e5fd05e155c05dd1fdaf569 while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); diff --git a/src/main/java/net/minecraft/world/entity/raid/Raider.java b/src/main/java/net/minecraft/world/entity/raid/Raider.java -index bbf21ea433f9e3963aac0ede597ed8d3c8e50ed8..bcf7a7d8137b62cd65ac3c6ff517025faa4f84b8 100644 +index ab132041982df2a701e4baea8195873f31b4a5fb..51ce6372d67224d7d03b528d45dd8ce7809a91ce 100644 --- a/src/main/java/net/minecraft/world/entity/raid/Raider.java +++ b/src/main/java/net/minecraft/world/entity/raid/Raider.java -@@ -89,7 +89,7 @@ public abstract class Raider extends PatrollingMonster { +@@ -92,7 +92,7 @@ public abstract class Raider extends PatrollingMonster { if (this.canJoinRaid()) { if (raid == null) { @@ -16157,7 +16676,7 @@ index bbf21ea433f9e3963aac0ede597ed8d3c8e50ed8..bcf7a7d8137b62cd65ac3c6ff517025f if (raid1 != null && Raids.canJoinRaid(this, raid1)) { diff --git a/src/main/java/net/minecraft/world/entity/raid/Raids.java b/src/main/java/net/minecraft/world/entity/raid/Raids.java -index 8c60f71270d909c10e6617eb64b8fdb42deb73e9..98b9f1c93824aa879395cd53057fdb4d3b8ae5d4 100644 +index 439d61d8689fabe940006b9b317a6810175dccfb..81ac4b7df5c402a618f6d7196b905ea065d6e822 100644 --- a/src/main/java/net/minecraft/world/entity/raid/Raids.java +++ b/src/main/java/net/minecraft/world/entity/raid/Raids.java @@ -26,9 +26,9 @@ import net.minecraft.world.phys.Vec3; @@ -16251,7 +16770,7 @@ index 8c60f71270d909c10e6617eb64b8fdb42deb73e9..98b9f1c93824aa879395cd53057fdb4d @@ -166,7 +183,7 @@ public class Raids extends SavedData { @Override - public CompoundTag save(CompoundTag nbt, HolderLookup.Provider registryLookup) { + public CompoundTag save(CompoundTag nbt, HolderLookup.Provider registries) { - nbt.putInt("NextAvailableID", this.nextAvailableID); + nbt.putInt("NextAvailableID", this.nextAvailableID.get()); // Folia - make raids thread-safe nbt.putInt("Tick", this.tick); @@ -16279,10 +16798,10 @@ index 8c60f71270d909c10e6617eb64b8fdb42deb73e9..98b9f1c93824aa879395cd53057fdb4d if (raid1.isActive() && d1 < d0) { diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java -index 83ef2c3e7b06152b9e68f90002c35e77f148347d..83d9b685aaf6934acfd0ca9a869723146ec7cfcb 100644 +index 56bae8ea1e7b115e85a701209f3badbd29912b28..c2e1d4572a3a625ee8f0d3d30e26febe71870c7d 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java -@@ -150,5 +150,11 @@ public class MinecartCommandBlock extends AbstractMinecart { +@@ -147,5 +147,11 @@ public class MinecartCommandBlock extends AbstractMinecart { return (org.bukkit.craftbukkit.entity.CraftMinecartCommand) MinecartCommandBlock.this.getBukkitEntity(); } // CraftBukkit end @@ -16295,10 +16814,10 @@ index 83ef2c3e7b06152b9e68f90002c35e77f148347d..83d9b685aaf6934acfd0ca9a86972314 } } diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java -index d7f8464bf3eed0e42a5fc7f14a5b243d171f8b5e..97bd1d7b4613c977376e43e180d8ec2a15acbcca 100644 +index d81a6874e8b25f098df619f84c359e146c7f64de..e56d580a89931aba43602a758fad803fbe45f25e 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartHopper.java -@@ -132,7 +132,7 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper +@@ -145,7 +145,7 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper // Paper start public void immunize() { @@ -16307,24 +16826,11 @@ index d7f8464bf3eed0e42a5fc7f14a5b243d171f8b5e..97bd1d7b4613c977376e43e180d8ec2a } // Paper end -diff --git a/src/main/java/net/minecraft/world/item/ArmorItem.java b/src/main/java/net/minecraft/world/item/ArmorItem.java -index 647a4601deace52f8d855f512a73671f82b4762a..255f6e720ebe0f76954fdba03cd2aae006852a78 100644 ---- a/src/main/java/net/minecraft/world/item/ArmorItem.java -+++ b/src/main/java/net/minecraft/world/item/ArmorItem.java -@@ -68,7 +68,7 @@ public class ArmorItem extends Item implements Equipable { - CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); - - BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityliving.getBukkitEntity()); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading - world.getCraftServer().getPluginManager().callEvent(event); - } - diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 522b817f23f08eb720fe9d05eec7f548d2761603..176ff4c3f367f2359303f7cd09d65b6adbc00a40 100644 +index 33e7d2884195677c4d6340d8b84c1dd85c636ec1..78fa9641be942539ba3a0b3f439dc917af1d69cd 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -421,31 +421,32 @@ public final class ItemStack implements DataComponentHolder { +@@ -424,31 +424,32 @@ public final class ItemStack implements DataComponentHolder { DataComponentPatch oldData = this.components.asPatch(); int oldCount = this.getCount(); ServerLevel world = (ServerLevel) context.getLevel(); @@ -16366,7 +16872,7 @@ index 522b817f23f08eb720fe9d05eec7f548d2761603..176ff4c3f367f2359303f7cd09d65b6a StructureGrowEvent structureEvent = null; if (treeType != null) { boolean isBonemeal = this.getItem() == Items.BONE_MEAL; -@@ -471,16 +472,16 @@ public final class ItemStack implements DataComponentHolder { +@@ -474,10 +475,10 @@ public final class ItemStack implements DataComponentHolder { entityhuman.awardStat(Stats.ITEM_USED.get(item)); // SPIGOT-7236 - award stat } @@ -16377,77 +16883,80 @@ index 522b817f23f08eb720fe9d05eec7f548d2761603..176ff4c3f367f2359303f7cd09d65b6a - world.captureTreeGeneration = false; + worldData.captureTreeGeneration = false; // Folia - region threading - if (entityhuman != null && enuminteractionresult.indicateItemUse()) { - InteractionHand enumhand = context.getHand(); - org.bukkit.event.block.BlockPlaceEvent placeEvent = null; -- List blocks = new java.util.ArrayList<>(world.capturedBlockStates.values()); -- world.capturedBlockStates.clear(); -+ List blocks = new java.util.ArrayList<>(worldData.capturedBlockStates.values()); // Folia - region threading -+ worldData.capturedBlockStates.clear(); // Folia - region threading - if (blocks.size() > 1) { - placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(world, entityhuman, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ()); - } else if (blocks.size() == 1 && item != Items.POWDER_SNOW_BUCKET) { // Paper - Fix cancelled powdered snow bucket placement -@@ -491,15 +492,15 @@ public final class ItemStack implements DataComponentHolder { - enuminteractionresult = InteractionResult.FAIL; // cancel placement - // PAIL: Remove this when MC-99075 fixed - placeEvent.getPlayer().updateInventory(); + if (entityhuman != null && enuminteractionresult instanceof InteractionResult.Success) { + InteractionResult.Success enuminteractionresult_d = (InteractionResult.Success) enuminteractionresult; +@@ -485,8 +486,8 @@ public final class ItemStack implements DataComponentHolder { + if (enuminteractionresult_d.wasItemInteraction()) { + InteractionHand enumhand = context.getHand(); + org.bukkit.event.block.BlockPlaceEvent placeEvent = null; +- List blocks = new java.util.ArrayList<>(world.capturedBlockStates.values()); +- world.capturedBlockStates.clear(); ++ List blocks = new java.util.ArrayList<>(worldData.capturedBlockStates.values()); // Folia - region threading ++ worldData.capturedBlockStates.clear(); // Folia - region threading + if (blocks.size() > 1) { + placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(world, entityhuman, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ()); + } else if (blocks.size() == 1 && item != Items.POWDER_SNOW_BUCKET) { // Paper - Fix cancelled powdered snow bucket placement +@@ -497,15 +498,15 @@ public final class ItemStack implements DataComponentHolder { + enuminteractionresult = InteractionResult.FAIL; // cancel placement + // PAIL: Remove this when MC-99075 fixed + placeEvent.getPlayer().updateInventory(); - world.capturedTileEntities.clear(); // Paper - Allow chests to be placed with NBT data; clear out block entities as chests and such will pop loot + worldData.capturedTileEntities.clear(); // Paper - Allow chests to be placed with NBT data; clear out block entities as chests and such will pop loot // Folia - region threading - // revert back all captured blocks -- world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710 + // revert back all captured blocks +- world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710 - world.isBlockPlaceCancelled = true; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent -+ worldData.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710 // Folia - region threading ++ worldData.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710 // Folia - region threading + worldData.isBlockPlaceCancelled = true; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent // Folia - region threading - for (BlockState blockstate : blocks) { - blockstate.update(true, false); - } -- world.isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent -- world.preventPoiUpdated = false; -+ worldData.isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent // Folia - region threading -+ worldData.preventPoiUpdated = false; // Folia - region threading - - // Brute force all possible updates - // Paper start - Don't resync blocks -@@ -508,7 +509,7 @@ public final class ItemStack implements DataComponentHolder { - // ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, placedPos.relative(dir))); - // } - // Paper end - Don't resync blocks -- SignItem.openSign = null; // SPIGOT-6758 - Reset on early return -+ SignItem.openSign.set(null); // SPIGOT-6758 - Reset on early return // Folia - region threading - } else { - // Change the stack to its new contents if it hasn't been tampered with. - if (this.getCount() == oldCount && Objects.equals(this.components.asPatch(), oldData)) { -@@ -516,7 +517,7 @@ public final class ItemStack implements DataComponentHolder { - this.setCount(newCount); - } - -- for (Map.Entry e : world.capturedTileEntities.entrySet()) { -+ for (Map.Entry e : worldData.capturedTileEntities.entrySet()) { // Folia - region threading - world.setBlockEntity(e.getValue()); - } - -@@ -551,15 +552,15 @@ public final class ItemStack implements DataComponentHolder { - } - - // SPIGOT-4678 -- if (this.item instanceof SignItem && SignItem.openSign != null) { -+ if (this.item instanceof SignItem && SignItem.openSign.get() != null) { // Folia - region threading - try { -- if (world.getBlockEntity(SignItem.openSign) instanceof SignBlockEntity tileentitysign) { -- if (world.getBlockState(SignItem.openSign).getBlock() instanceof SignBlock blocksign) { -+ if (world.getBlockEntity(SignItem.openSign.get()) instanceof SignBlockEntity tileentitysign) { // Folia - region threading -+ if (world.getBlockState(SignItem.openSign.get()).getBlock() instanceof SignBlock blocksign) { // Folia - region threading - blocksign.openTextEdit(entityhuman, tileentitysign, true, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLACE); // Paper - Add PlayerOpenSignEvent - } - } - } finally { -- SignItem.openSign = null; -+ SignItem.openSign.set(null); // Folia - region threading + for (BlockState blockstate : blocks) { + blockstate.update(true, false); } - } +- world.isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent +- world.preventPoiUpdated = false; ++ worldData.isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent // Folia - region threading ++ worldData.preventPoiUpdated = false; // Folia - region threading -@@ -587,8 +588,8 @@ public final class ItemStack implements DataComponentHolder { - entityhuman.awardStat(Stats.ITEM_USED.get(item)); + // Brute force all possible updates + // Paper start - Don't resync blocks +@@ -514,7 +515,7 @@ public final class ItemStack implements DataComponentHolder { + // ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, placedPos.relative(dir))); + // } + // Paper end - Don't resync blocks +- SignItem.openSign = null; // SPIGOT-6758 - Reset on early return ++ SignItem.openSign.set(null); // SPIGOT-6758 - Reset on early return // Folia - region threading + } else { + // Change the stack to its new contents if it hasn't been tampered with. + if (this.getCount() == oldCount && Objects.equals(this.components.asPatch(), oldData)) { +@@ -522,7 +523,7 @@ public final class ItemStack implements DataComponentHolder { + this.setCount(newCount); + } + +- for (Map.Entry e : world.capturedTileEntities.entrySet()) { ++ for (Map.Entry e : worldData.capturedTileEntities.entrySet()) { // Folia - region threading + world.setBlockEntity(e.getValue()); + } + +@@ -557,15 +558,15 @@ public final class ItemStack implements DataComponentHolder { + } + + // SPIGOT-4678 +- if (this.item instanceof SignItem && SignItem.openSign != null) { ++ if (this.item instanceof SignItem && SignItem.openSign.get() != null) { // Folia - region threading + try { +- if (world.getBlockEntity(SignItem.openSign) instanceof SignBlockEntity tileentitysign) { +- if (world.getBlockState(SignItem.openSign).getBlock() instanceof SignBlock blocksign) { ++ if (world.getBlockEntity(SignItem.openSign.get()) instanceof SignBlockEntity tileentitysign) { // Folia - region threading ++ if (world.getBlockState(SignItem.openSign.get()).getBlock() instanceof SignBlock blocksign) { // Folia - region threading + blocksign.openTextEdit(entityhuman, tileentitysign, true, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLACE); // Craftbukkit // Paper - Add PlayerOpenSignEvent + } + } + } finally { +- SignItem.openSign = null; ++ SignItem.openSign.set(null); // Folia - region threading + } + } + +@@ -594,8 +595,8 @@ public final class ItemStack implements DataComponentHolder { + } } } - world.capturedTileEntities.clear(); @@ -16458,10 +16967,10 @@ index 522b817f23f08eb720fe9d05eec7f548d2761603..176ff4c3f367f2359303f7cd09d65b6a return enuminteractionresult; diff --git a/src/main/java/net/minecraft/world/item/MapItem.java b/src/main/java/net/minecraft/world/item/MapItem.java -index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..e96f15814986109e5e947c7b3b210be6e56ba0ed 100644 +index 571f2540a1e9422025efe651167e26b44b437daa..58f3c9598301a5b34142ddf958aa7a4db634be3d 100644 --- a/src/main/java/net/minecraft/world/item/MapItem.java +++ b/src/main/java/net/minecraft/world/item/MapItem.java -@@ -69,6 +69,7 @@ public class MapItem extends ComplexItem { +@@ -68,6 +68,7 @@ public class MapItem extends Item { } public void update(Level world, Entity entity, MapItemSavedData state) { @@ -16469,7 +16978,7 @@ index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..e96f15814986109e5e947c7b3b210be6 if (world.dimension() == state.dimension && entity instanceof Player) { int i = 1 << state.scale; int j = state.centerX; -@@ -98,8 +99,8 @@ public class MapItem extends ComplexItem { +@@ -97,8 +98,8 @@ public class MapItem extends Item { int r = (j / i + o - 64) * i; int s = (k / i + p - 64) * i; Multiset multiset = LinkedHashMultiset.create(); @@ -16480,7 +16989,7 @@ index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..e96f15814986109e5e947c7b3b210be6 int t = 0; double e = 0.0; if (world.dimensionType().hasCeiling()) { -@@ -181,6 +182,7 @@ public class MapItem extends ComplexItem { +@@ -180,6 +181,7 @@ public class MapItem extends Item { } } } @@ -16488,7 +16997,7 @@ index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..e96f15814986109e5e947c7b3b210be6 } private BlockState getCorrectStateForFluidBlock(Level world, BlockState state, BlockPos pos) { -@@ -195,6 +197,7 @@ public class MapItem extends ComplexItem { +@@ -194,6 +196,7 @@ public class MapItem extends Item { public static void renderBiomePreviewMap(ServerLevel world, ItemStack map) { MapItemSavedData mapItemSavedData = getSavedData(map, world); if (mapItemSavedData != null) { @@ -16496,7 +17005,7 @@ index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..e96f15814986109e5e947c7b3b210be6 if (world.dimension() == mapItemSavedData.dimension) { int i = 1 << mapItemSavedData.scale; int j = mapItemSavedData.centerX; -@@ -264,6 +267,7 @@ public class MapItem extends ComplexItem { +@@ -263,6 +266,7 @@ public class MapItem extends Item { } } } @@ -16504,7 +17013,7 @@ index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..e96f15814986109e5e947c7b3b210be6 } } -@@ -272,6 +276,7 @@ public class MapItem extends ComplexItem { +@@ -271,6 +275,7 @@ public class MapItem extends Item { if (!world.isClientSide) { MapItemSavedData mapItemSavedData = getSavedData(stack, world); if (mapItemSavedData != null) { @@ -16512,7 +17021,7 @@ index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..e96f15814986109e5e947c7b3b210be6 if (entity instanceof Player player) { mapItemSavedData.tickCarriedBy(player, stack); } -@@ -279,6 +284,7 @@ public class MapItem extends ComplexItem { +@@ -278,6 +283,7 @@ public class MapItem extends Item { if (!mapItemSavedData.locked && (selected || entity instanceof Player && ((Player)entity).getOffhandItem() == stack)) { this.update(world, entity, mapItemSavedData); } @@ -16520,21 +17029,8 @@ index ce461b1a8d7fab87ae28e30205f6fab67f1808b6..e96f15814986109e5e947c7b3b210be6 } } } -diff --git a/src/main/java/net/minecraft/world/item/MinecartItem.java b/src/main/java/net/minecraft/world/item/MinecartItem.java -index d524fcc191cb95d6ec7f12ae7fceeb8077bb08fc..dd5a4463f4b0273f5c7491a3c78567e3ac6a3351 100644 ---- a/src/main/java/net/minecraft/world/item/MinecartItem.java -+++ b/src/main/java/net/minecraft/world/item/MinecartItem.java -@@ -71,7 +71,7 @@ public class MinecartItem extends Item { - CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); - - BlockDispenseEvent event = new BlockDispenseEvent(block2, craftItem.clone(), new org.bukkit.util.Vector(d0, d1 + d3, d2)); -- if (!DispenserBlock.eventFired) { -+ if (!DispenserBlock.eventFired.get()) { // Folia - region threading - worldserver.getCraftServer().getPluginManager().callEvent(event); - } - diff --git a/src/main/java/net/minecraft/world/item/SignItem.java b/src/main/java/net/minecraft/world/item/SignItem.java -index 21c25026da4117b2cb2c85576d2def945a97dbe2..e0b51cb4ef9e847dc9a2e66f2c87c94d6d93c6a3 100644 +index fcc78491cef1cf1535888c4ed43c3b71fb597848..d6ff4ad0b9fbba491e6d0c96aaa62a2eaca89fd6 100644 --- a/src/main/java/net/minecraft/world/item/SignItem.java +++ b/src/main/java/net/minecraft/world/item/SignItem.java @@ -13,7 +13,7 @@ import net.minecraft.world.level.block.state.BlockState; @@ -16544,8 +17040,8 @@ index 21c25026da4117b2cb2c85576d2def945a97dbe2..e0b51cb4ef9e847dc9a2e66f2c87c94d - public static BlockPos openSign; // CraftBukkit + public static final ThreadLocal openSign = new ThreadLocal<>(); // CraftBukkit // Folia - region threading - public SignItem(Item.Properties settings, Block standingBlock, Block wallBlock) { - super(standingBlock, wallBlock, settings, Direction.DOWN); + public SignItem(Block standingBlock, Block wallBlock, Item.Properties settings) { + super(standingBlock, wallBlock, Direction.DOWN, settings); @@ -39,7 +39,7 @@ public class SignItem extends StandingAndWallBlockItem { // CraftBukkit start - SPIGOT-4678 @@ -16556,7 +17052,7 @@ index 21c25026da4117b2cb2c85576d2def945a97dbe2..e0b51cb4ef9e847dc9a2e66f2c87c94d } } diff --git a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java -index e6bfcc50cdf728216084bc00a5bb8b6b3b8f72e4..b8a571fcc44f67ac8f6089e039a8620bf6c40603 100644 +index 5cb39f95bd2d45b6c18554605f01d2ebf6473428..ccf476d1ed22cf992e3cbca6a375d36f85a82fa8 100644 --- a/src/main/java/net/minecraft/world/level/BaseCommandBlock.java +++ b/src/main/java/net/minecraft/world/level/BaseCommandBlock.java @@ -22,7 +22,7 @@ import net.minecraft.world.phys.Vec3; @@ -16593,10 +17089,10 @@ index e6bfcc50cdf728216084bc00a5bb8b6b3b8f72e4..b8a571fcc44f67ac8f6089e039a8620b this.lastOutput = Component.literal("[" + simpledateformat.format(date) + "] ").append(message); diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index 141b748abe80402731cdaf14a3d36aa7cef4f4bd..95938efe2282a024d9d428dedd16cbe127d3ffed 100644 +index 5d7a6e4b73f032db356e7ec369b150013e940ee6..6e895ca2844fd2d8189a6cf173d0c5dc9aaf02a9 100644 --- a/src/main/java/net/minecraft/world/level/EntityGetter.java +++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -27,6 +27,12 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst +@@ -24,6 +24,12 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst return this.getEntities(EntityTypeTest.forClass(entityClass), box, predicate); } @@ -16609,7 +17105,7 @@ index 141b748abe80402731cdaf14a3d36aa7cef4f4bd..95938efe2282a024d9d428dedd16cbe1 List players(); default List getEntities(@Nullable Entity except, AABB box) { -@@ -125,7 +131,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst +@@ -122,7 +128,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst double d = -1.0; Player player = null; @@ -16618,7 +17114,7 @@ index 141b748abe80402731cdaf14a3d36aa7cef4f4bd..95938efe2282a024d9d428dedd16cbe1 if (targetPredicate == null || targetPredicate.test(player2)) { double e = player2.distanceToSqr(x, y, z); if ((maxDistance < 0.0 || e < maxDistance * maxDistance) && (d == -1.0 || e < d)) { -@@ -146,7 +152,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst +@@ -143,7 +149,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst default List findNearbyBukkitPlayers(double x, double y, double z, double radius, @Nullable Predicate predicate) { com.google.common.collect.ImmutableList.Builder builder = com.google.common.collect.ImmutableList.builder(); @@ -16627,7 +17123,7 @@ index 141b748abe80402731cdaf14a3d36aa7cef4f4bd..95938efe2282a024d9d428dedd16cbe1 if (predicate == null || predicate.test(human)) { double distanceSquared = human.distanceToSqr(x, y, z); -@@ -173,7 +179,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst +@@ -170,7 +176,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst // Paper start - Affects Spawning API default boolean hasNearbyAlivePlayerThatAffectsSpawning(double x, double y, double z, double range) { @@ -16636,7 +17132,7 @@ index 141b748abe80402731cdaf14a3d36aa7cef4f4bd..95938efe2282a024d9d428dedd16cbe1 if (EntitySelector.PLAYER_AFFECTS_SPAWNING.test(player)) { // combines NO_SPECTATORS and LIVING_ENTITY_STILL_ALIVE with an "affects spawning" check double distanceSqr = player.distanceToSqr(x, y, z); if (range < 0.0D || distanceSqr < range * range) { -@@ -186,7 +192,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst +@@ -183,7 +189,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst // Paper end - Affects Spawning API default boolean hasNearbyAlivePlayer(double x, double y, double z, double range) { @@ -16645,37 +17141,7 @@ index 141b748abe80402731cdaf14a3d36aa7cef4f4bd..95938efe2282a024d9d428dedd16cbe1 if (EntitySelector.NO_SPECTATORS.test(player) && EntitySelector.LIVING_ENTITY_STILL_ALIVE.test(player)) { double d = player.distanceToSqr(x, y, z); if (range < 0.0 || d < range * range) { -@@ -200,17 +206,17 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst - - @Nullable - default Player getNearestPlayer(TargetingConditions targetPredicate, LivingEntity entity) { -- return this.getNearestEntity(this.players(), targetPredicate, entity, entity.getX(), entity.getY(), entity.getZ()); -+ return this.getNearestEntity(this.getLocalPlayers(), targetPredicate, entity, entity.getX(), entity.getY(), entity.getZ()); // Folia - region threading - } - - @Nullable - default Player getNearestPlayer(TargetingConditions targetPredicate, LivingEntity entity, double x, double y, double z) { -- return this.getNearestEntity(this.players(), targetPredicate, entity, x, y, z); -+ return this.getNearestEntity(this.getLocalPlayers(), targetPredicate, entity, x, y, z); // Folia - region threading - } - - @Nullable - default Player getNearestPlayer(TargetingConditions targetPredicate, double x, double y, double z) { -- return this.getNearestEntity(this.players(), targetPredicate, null, x, y, z); -+ return this.getNearestEntity(this.getLocalPlayers(), targetPredicate, null, x, y, z); // Folia - region threading - } - - @Nullable -@@ -243,7 +249,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst - default List getNearbyPlayers(TargetingConditions targetPredicate, LivingEntity entity, AABB box) { - List list = Lists.newArrayList(); - -- for (Player player : this.players()) { -+ for (Player player : this.getLocalPlayers()) { // Folia - region threading - if (box.contains(player.getX(), player.getY(), player.getZ()) && targetPredicate.test(entity, player)) { - list.add(player); - } -@@ -269,8 +275,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst +@@ -197,8 +203,7 @@ public interface EntityGetter extends ca.spottedleaf.moonrise.patches.chunk_syst @Nullable default Player getPlayerByUUID(UUID uuid) { @@ -16686,36 +17152,27 @@ index 141b748abe80402731cdaf14a3d36aa7cef4f4bd..95938efe2282a024d9d428dedd16cbe1 return player; } diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index f696afd7e241bf1966a2d505b5d59bff824b43e4..e642638f70dffab027f8c538889e3b17da1c29df 100644 +index 952c866bed29b412a48332ba1d98515f0f069781..68710af738fe6de115b75135f0f301763cb63b33 100644 --- a/src/main/java/net/minecraft/world/level/Explosion.java +++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -845,17 +845,18 @@ public class Explosion { - if (!this.level.paperConfig().environment.optimizeExplosions) { - return this.getSeenFraction(vec3d, entity, blockCache, blockPos); // Paper - optimise collisions - } -+ io.papermc.paper.threadedregions.RegionizedWorldData worldData = this.level.getCurrentWorldData(); // Folia - region threading - CacheKey key = new CacheKey(this, entity.getBoundingBox()); -- Float blockDensity = this.level.explosionDensityCache.get(key); -+ Float blockDensity = worldData.explosionDensityCache.get(key); // Folia - region threading - if (blockDensity == null) { - blockDensity = this.getSeenFraction(vec3d, entity, blockCache, blockPos); // Paper - optimise collisions -- this.level.explosionDensityCache.put(key, blockDensity); -+ worldData.explosionDensityCache.put(key, blockDensity); // Folia - region threading - } - - return blockDensity; +@@ -17,10 +17,11 @@ public interface Explosion { + @Nullable + static LivingEntity getIndirectSourceEntity(@Nullable Entity entity) { + return switch (entity) { +- case null, default -> null; ++ // Folia - decompile error - move down + case PrimedTnt primedTnt -> primedTnt.getOwner(); + case LivingEntity livingEntity -> livingEntity; + case Projectile projectile when projectile.getOwner() instanceof LivingEntity livingEntity2 -> livingEntity2; ++ case null, default -> null; // Folia - decompile error - moved down + }; } -- static class CacheKey { -+ public static class CacheKey { // Folia - region threading - public - private final Level world; - private final double posX, posY, posZ; - private final double minX, minY, minZ; diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f0c93b792 100644 +index 0de2b79481352b52438dde284262019b29949ad8..35b18a9ecce6c7b743badbf384f40b48f2fc73be 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -116,10 +116,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -118,10 +118,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public static final int TICKS_PER_DAY = 24000; public static final int MAX_ENTITY_SPAWN_Y = 20000000; public static final int MIN_ENTITY_SPAWN_Y = -20000000; @@ -16730,16 +17187,16 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f public final Thread thread; private final boolean isDebug; private int skyDarken; -@@ -129,7 +129,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -131,7 +131,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public float rainLevel; protected float oThunderLevel; public float thunderLevel; -- public final RandomSource random = RandomSource.create(); -+ public final RandomSource random = new Entity.RandomRandomSource(); // Folia - region threading +- public final RandomSource random = new ca.spottedleaf.moonrise.common.util.ThreadUnsafeRandom(net.minecraft.world.level.levelgen.RandomSupport.generateUniqueSeed()); // Paper - replace random ++ public final RandomSource random = io.papermc.paper.threadedregions.util.ThreadLocalRandomSource.INSTANCE; // Folia - region threading /** @deprecated */ @Deprecated private final RandomSource threadSafeRandom = RandomSource.createThreadSafe(); -@@ -142,28 +142,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -143,28 +143,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl private final ResourceKey dimension; private final RegistryAccess registryAccess; private final DamageSources damageSources; @@ -16777,15 +17234,15 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f private org.spigotmc.TickLimiter entityLimiter; private org.spigotmc.TickLimiter tileLimiter; - private int tileTickPosition; -- public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions +- public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions - public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Faster redstone torch rapid clock removal; Move from Map in BlockRedstoneTorch to here + //private int tileTickPosition; // Folia - region threading -+ //public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions // Folia - region threading ++ //public final Map explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions // Folia - region threading + //public java.util.ArrayDeque redstoneUpdateInfos; // Paper - Faster redstone torch rapid clock removal; Move from Map in BlockRedstoneTorch to here // Folia - region threading public CraftWorld getWorld() { return this.world; -@@ -683,6 +672,32 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -829,6 +818,32 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl return chunk != null ? chunk.getNoiseBiome(x, y, z) : this.getUncachedNoiseBiome(x, y, z); } // Paper end - optimise random ticking @@ -16816,9 +17273,9 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f + } + // Folia end - region ticking - protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config & Anti-Xray - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot -@@ -724,7 +739,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config & Anti-Xray + // Paper start - getblock optimisations - cache world height/sections +@@ -878,7 +893,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl this.thread = Thread.currentThread(); this.biomeManager = new BiomeManager(this, i); this.isDebug = flag1; @@ -16827,7 +17284,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f this.registryAccess = iregistrycustom; this.damageSources = new DamageSources(iregistrycustom); // CraftBukkit start -@@ -951,8 +966,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1023,8 +1038,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Nullable public final BlockState getBlockStateIfLoaded(BlockPos pos) { // CraftBukkit start - tree generation @@ -16838,7 +17295,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f if (previous != null) { return previous.getHandle(); } -@@ -1014,16 +1029,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1086,16 +1101,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { @@ -16860,7 +17317,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f } blockstate.setData(state); blockstate.setFlag(flags); -@@ -1040,10 +1057,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1112,10 +1129,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl // CraftBukkit start - capture blockstates boolean captured = false; @@ -16873,7 +17330,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f captured = true; } // CraftBukkit end -@@ -1053,8 +1070,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1125,8 +1142,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl if (iblockdata1 == null) { // CraftBukkit start - remove blockstate if failed (or the same) @@ -16884,7 +17341,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f } // CraftBukkit end return false; -@@ -1091,7 +1108,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1163,7 +1180,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl */ // CraftBukkit start @@ -16893,7 +17350,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f // Modularize client and physic updates // Spigot start try { -@@ -1136,7 +1153,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1208,7 +1225,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam CraftWorld world = ((ServerLevel) this).getWorld(); boolean cancelledUpdates = false; // Paper - Fix block place logic @@ -16902,7 +17359,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); this.getCraftServer().getPluginManager().callEvent(event); -@@ -1150,7 +1167,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1222,7 +1239,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } // CraftBukkit start - SPIGOT-5710 @@ -16911,16 +17368,16 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); } // CraftBukkit end -@@ -1234,7 +1251,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1308,7 +1325,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override - public void neighborShapeChanged(Direction direction, BlockState neighborState, BlockPos pos, BlockPos neighborPos, int flags, int maxUpdateDepth) { + public void neighborShapeChanged(Direction direction, BlockPos pos, BlockPos neighborPos, BlockState neighborState, int flags, int maxUpdateDepth) { - this.neighborUpdater.shapeUpdate(direction, neighborState, pos, neighborPos, flags, maxUpdateDepth); + this.getCurrentWorldData().neighborUpdater.shapeUpdate(direction, neighborState, pos, neighborPos, flags, maxUpdateDepth); // Folia - region threading } @Override -@@ -1259,11 +1276,34 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1333,11 +1350,34 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl return this.getChunkSource().getLightEngine(); } @@ -16957,7 +17414,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f if (previous != null) { return previous.getHandle(); } -@@ -1362,7 +1402,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1436,18 +1476,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } public void addBlockEntityTicker(TickingBlockEntity ticker) { @@ -16966,10 +17423,9 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f } protected void tickBlockEntities() { -@@ -1370,11 +1410,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + ProfilerFiller gameprofilerfiller = Profiler.get(); gameprofilerfiller.push("blockEntities"); - this.timings.tileEntityPending.startTiming(); // Spigot - this.tickingBlockEntities = true; - if (!this.pendingBlockEntityTickers.isEmpty()) { - this.blockEntityTickers.addAll(this.pendingBlockEntityTickers); @@ -16979,10 +17435,10 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f + regionizedWorldData.seTtickingBlockEntities(true); // Folia - regionised ticking + regionizedWorldData.pushPendingTickingBlockEntities(); // Folia - regionised ticking + List blockEntityTickers = regionizedWorldData.getBlockEntityTickers(); // Folia - regionised ticking - this.timings.tileEntityPending.stopTiming(); // Spigot - this.timings.tileEntityTick.startTiming(); // Spigot -@@ -1387,9 +1426,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + // Spigot start + // Iterator iterator = this.blockEntityTickers.iterator(); +@@ -1458,9 +1497,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl int tilesThisCycle = 0; var toRemove = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet(); // Paper - Fix MC-117075; use removeAll toRemove.add(null); // Paper - Fix MC-117075 @@ -16994,25 +17450,22 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f // Spigot end if (tickingblockentity.isRemoved()) { -@@ -1406,13 +1444,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1477,11 +1515,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl // Paper end - rewrite chunk system } } - this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 + blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 // Folia - regionised ticking - this.timings.tileEntityTick.stopTiming(); // Spigot - this.tickingBlockEntities = false; -- co.aikar.timings.TimingHistory.tileEntityTicks += this.blockEntityTickers.size(); // Paper + regionizedWorldData.seTtickingBlockEntities(false); // Folia - regionised ticking -+ //co.aikar.timings.TimingHistory.tileEntityTicks += this.blockEntityTickers.size(); // Paper // Folia - region threading gameprofilerfiller.pop(); - this.spigotConfig.currentPrimedTnt = 0; // Spigot + regionizedWorldData.currentPrimedTnt = 0; // Spigot // Folia - region threading } public void guardEntityTick(Consumer tickConsumer, T entity) { -@@ -1424,7 +1462,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1493,7 +1531,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ()); MinecraftServer.LOGGER.error(msg, throwable); getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable))); // Paper - ServerExceptionEvent @@ -17022,7 +17475,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f // Paper end - Prevent block entity and entity crashes } this.moonrise$midTickTasks(); // Paper - rewrite chunk system -@@ -1544,9 +1583,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1554,9 +1593,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Nullable public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) { @@ -17038,7 +17491,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f return blockEntity; } // Paper end - Perf: Optimize capturedTileEntities lookup -@@ -1559,8 +1603,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1569,8 +1613,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl if (!this.isOutsideBuildHeight(blockposition)) { // CraftBukkit start @@ -17049,39 +17502,43 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f return; } // CraftBukkit end -@@ -1640,6 +1684,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1650,6 +1694,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public List getEntities(@Nullable Entity except, AABB box, Predicate predicate) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread((ServerLevel)this, box, "Cannot getEntities asynchronously"); // Folia - region threading - this.getProfiler().incrementCounter("getEntities"); - // Paper start - rewrite chunk system - final List ret = new java.util.ArrayList<>(); -@@ -1666,6 +1711,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + Profiler.get().incrementCounter("getEntities"); + List list = Lists.newArrayList(); + +@@ -1680,6 +1725,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public void getEntities(final EntityTypeTest entityTypeTest, final AABB boundingBox, final Predicate predicate, final List into, final int maxCount) { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this, boundingBox, "Cannot getEntities asynchronously"); // Folia - region threading - this.getProfiler().incrementCounter("getEntities"); + Profiler.get().incrementCounter("getEntities"); if (entityTypeTest instanceof net.minecraft.world.entity.EntityType byType) { -@@ -1751,13 +1797,30 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1777,13 +1823,34 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public void disconnect() {} + @Override // Folia - region threading public long getGameTime() { - return this.levelData.getGameTime(); ++ // Folia start - region threading + // Dumb world gen thread calls this for some reason. So, check for null. + io.papermc.paper.threadedregions.RegionizedWorldData worldData = this.getCurrentWorldData(); + return worldData == null ? this.getLevelData().getGameTime() : worldData.getTickData().nonRedstoneGameTime(); ++ // Folia end - region threading } public long getDayTime() { - return this.levelData.getDayTime(); ++ // Folia start - region threading + // Dumb world gen thread calls this for some reason. So, check for null. + io.papermc.paper.threadedregions.RegionizedWorldData worldData = this.getCurrentWorldData(); + return worldData == null ? this.getLevelData().getDayTime() : worldData.getTickData().dayTime(); ++ // Folia end - region threading + } + + // Folia start - region threading @@ -17098,8 +17555,8 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f public boolean mayInteract(Player player, BlockPos pos) { return true; -@@ -1950,8 +2013,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - public abstract RecipeManager getRecipeManager(); +@@ -1976,8 +2043,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + public abstract RecipeAccess recipeAccess(); public BlockPos getBlockRandomPos(int x, int y, int z, int l) { - this.randValue = this.randValue * 3 + 1013904223; @@ -17108,7 +17565,7 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f return new BlockPos(x + (i1 & 15), y + (i1 >> 16 & l), z + (i1 >> 8 & 15)); } -@@ -1981,7 +2043,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1999,7 +2065,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl @Override public long nextSubTickCount() { @@ -17118,12 +17575,12 @@ index 507671476c3d2d92a2fdb05be24443af27d26dcf..d518487433088f090edb0d12e222b85f @Override diff --git a/src/main/java/net/minecraft/world/level/LevelAccessor.java b/src/main/java/net/minecraft/world/level/LevelAccessor.java -index 54d13eebc9b01e9d77f51011b7de95b80bc21669..47c3e7f15e1ba9ea8a1c1bb1a0af61dd78dc1b85 100644 +index e5c5698fd74cb916467bccead8c1f323c6e3cbb0..9bfb933a2b2af849286d53bd05a77ee3c1f9e665 100644 --- a/src/main/java/net/minecraft/world/level/LevelAccessor.java +++ b/src/main/java/net/minecraft/world/level/LevelAccessor.java -@@ -38,12 +38,22 @@ public interface LevelAccessor extends CommonLevelAccessor, LevelTimeAccess { +@@ -34,14 +34,24 @@ public interface LevelAccessor extends CommonLevelAccessor, LevelTimeAccess, Sch - LevelTickAccess getBlockTicks(); + long nextSubTickCount(); + // Folia start - region threading + default long getGameTime() { @@ -17135,23 +17592,25 @@ index 54d13eebc9b01e9d77f51011b7de95b80bc21669..47c3e7f15e1ba9ea8a1c1bb1a0af61dd + } + // Folia end - region threading + - private ScheduledTick createTick(BlockPos pos, T type, int delay, TickPriority priority) { + @Override + default ScheduledTick createTick(BlockPos pos, T type, int delay, TickPriority priority) { - return new ScheduledTick<>(type, pos, this.getLevelData().getGameTime() + (long) delay, priority, this.nextSubTickCount()); + return new ScheduledTick<>(type, pos, this.getRedstoneGameTime() + (long) delay, priority, this.nextSubTickCount()); // Folia - region threading } - private ScheduledTick createTick(BlockPos pos, T type, int delay) { + @Override + default ScheduledTick createTick(BlockPos pos, T type, int delay) { - return new ScheduledTick<>(type, pos, this.getLevelData().getGameTime() + (long) delay, this.nextSubTickCount()); + return new ScheduledTick<>(type, pos, this.getRedstoneGameTime() + (long) delay, this.nextSubTickCount()); // Folia - region threading } - default void scheduleTick(BlockPos pos, Block block, int delay, TickPriority priority) { + LevelData getLevelData(); diff --git a/src/main/java/net/minecraft/world/level/LevelReader.java b/src/main/java/net/minecraft/world/level/LevelReader.java -index 1a4dc4b2561dbaf01246b4fb46266b1ac84008b8..345090afeab4f6396244c50bdbe8320887e15d7e 100644 +index ade435de0af4ee3566fa4a490df53cddd2f6531c..8fd969d3fe8c9ea8dcb53b4187897b401d1af4a1 100644 --- a/src/main/java/net/minecraft/world/level/LevelReader.java +++ b/src/main/java/net/minecraft/world/level/LevelReader.java -@@ -207,6 +207,25 @@ public interface LevelReader extends ca.spottedleaf.moonrise.patches.chunk_syste - return maxY >= this.getMinBuildHeight() && minY < this.getMaxBuildHeight() && this.hasChunksAt(minX, minZ, maxX, maxZ); +@@ -206,6 +206,25 @@ public interface LevelReader extends ca.spottedleaf.moonrise.patches.chunk_syste + return maxY >= this.getMinY() && minY <= this.getMaxY() && this.hasChunksAt(minX, minZ, maxX, maxZ); } + // Folia start - region threading @@ -17177,18 +17636,44 @@ index 1a4dc4b2561dbaf01246b4fb46266b1ac84008b8..345090afeab4f6396244c50bdbe83208 default boolean hasChunksAt(int minX, int minZ, int maxX, int maxZ) { int i = SectionPos.blockToSectionCoord(minX); diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -index 743a33ae2814c513b84b1a60e50a3c24527568f8..1023b0d4f52a79bc4db27130d47b6c93b464794a 100644 +index c1b76a1ebc1eea7ab70cf61d8175a31794dd122a..5403794f9613ecd976769240ccecd3c174118b46 100644 --- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java +++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java -@@ -141,7 +141,7 @@ public final class NaturalSpawner { +@@ -145,7 +145,7 @@ public final class NaturalSpawner { int limit = enumcreaturetype.getMaxInstancesPerChunk(); SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(enumcreaturetype); if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { -- spawnThisTick = world.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worlddata.getGameTime() % world.ticksPerSpawnCategory.getLong(spawnCategory) == 0; -+ spawnThisTick = world.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && world.getRedstoneGameTime() % world.ticksPerSpawnCategory.getLong(spawnCategory) == 0; // Folia - region threading - limit = world.getWorld().getSpawnLimit(spawnCategory); +- spawnThisTick = worldserver.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worlddata.getGameTime() % worldserver.ticksPerSpawnCategory.getLong(spawnCategory) == 0; ++ spawnThisTick = worldserver.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worldserver.getRedstoneGameTime() % worldserver.ticksPerSpawnCategory.getLong(spawnCategory) == 0; // Folia - region threading + limit = worldserver.getWorld().getSpawnLimit(spawnCategory); } +diff --git a/src/main/java/net/minecraft/world/level/ServerExplosion.java b/src/main/java/net/minecraft/world/level/ServerExplosion.java +index bbbd451ff184be8fa13bd93d53c89a9502f9951a..93b2bf5f518084c18cfeef0cbc9edc61225e67f9 100644 +--- a/src/main/java/net/minecraft/world/level/ServerExplosion.java ++++ b/src/main/java/net/minecraft/world/level/ServerExplosion.java +@@ -791,17 +791,18 @@ public class ServerExplosion implements Explosion { + if (!this.level.paperConfig().environment.optimizeExplosions) { + return this.getSeenFraction(vec3d, entity, this.directMappedBlockCache, this.mutablePos); // Paper - collision optimisations + } ++ io.papermc.paper.threadedregions.RegionizedWorldData worldData = this.level.getCurrentWorldData(); // Folia - region threading + CacheKey key = new CacheKey(this, entity.getBoundingBox()); +- Float blockDensity = this.level.explosionDensityCache.get(key); ++ Float blockDensity = worldData.explosionDensityCache.get(key); // Folia - region threading + if (blockDensity == null) { + blockDensity = this.getSeenFraction(vec3d, entity, this.directMappedBlockCache, this.mutablePos); // Paper - collision optimisations +- this.level.explosionDensityCache.put(key, blockDensity); ++ worldData.explosionDensityCache.put(key, blockDensity); // Folia - region threading + } + + return blockDensity; + } + +- static class CacheKey { ++ public static class CacheKey { // Folia - region threading - public + private final Level world; + private final double posX, posY, posZ; + private final double minX, minY, minZ; diff --git a/src/main/java/net/minecraft/world/level/ServerLevelAccessor.java b/src/main/java/net/minecraft/world/level/ServerLevelAccessor.java index 3d377b9e461040405e0a7dcbd72d1506b48eb44e..782890e227ff9dab44dd92327979c201985f116e 100644 --- a/src/main/java/net/minecraft/world/level/ServerLevelAccessor.java @@ -17207,7 +17692,7 @@ index 3d377b9e461040405e0a7dcbd72d1506b48eb44e..782890e227ff9dab44dd92327979c201 // CraftBukkit start this.addFreshEntityWithPassengers(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); diff --git a/src/main/java/net/minecraft/world/level/StructureManager.java b/src/main/java/net/minecraft/world/level/StructureManager.java -index 54972cce2314eff774250101df43a9b7074e9604..0c4942895a83ce1392dd1e71a00ab6d0cb15dab7 100644 +index 03adb02297911e5a5051edac14453d7e3eeac29c..cd2785d084225e8a166b21324d830cf20298c439 100644 --- a/src/main/java/net/minecraft/world/level/StructureManager.java +++ b/src/main/java/net/minecraft/world/level/StructureManager.java @@ -48,11 +48,7 @@ public class StructureManager { @@ -17223,7 +17708,7 @@ index 54972cce2314eff774250101df43a9b7074e9604..0c4942895a83ce1392dd1e71a00ab6d0 // Paper end - Fix swamp hut cat generation deadlock Builder builder = ImmutableList.builder(); -@@ -121,20 +117,11 @@ public class StructureManager { +@@ -121,20 +117,12 @@ public class StructureManager { } public StructureStart getStructureWithPieceAt(BlockPos pos, Predicate> predicate) { @@ -17236,17 +17721,17 @@ index 54972cce2314eff774250101df43a9b7074e9604..0c4942895a83ce1392dd1e71a00ab6d0 - } - - public StructureStart getStructureWithPieceAt(BlockPos pos, Predicate> predicate, @Nullable ServerLevelAccessor levelAccessor) { -- // Paper end - Fix swamp hut cat generation deadlock + // Folia - region threading - Registry registry = this.registryAccess().registryOrThrow(Registries.STRUCTURE); + // Paper end - Fix swamp hut cat generation deadlock + Registry registry = this.registryAccess().lookupOrThrow(Registries.STRUCTURE); for (StructureStart structureStart : this.startsForStructure( -- new ChunkPos(pos), structure -> registry.getHolder(registry.getId(structure)).map(predicate::test).orElse(false), levelAccessor // Paper - Fix swamp hut cat generation deadlock -+ new ChunkPos(pos), structure -> registry.getHolder(registry.getId(structure)).map(predicate::test).orElse(false) // Paper - Fix swamp hut cat generation deadlock // Folia - region threading +- new ChunkPos(pos), structure -> registry.get(registry.getId(structure)).map(predicate::test).orElse(false), levelAccessor // Paper - Fix swamp hut cat generation deadlock ++ new ChunkPos(pos), structure -> registry.get(registry.getId(structure)).map(predicate::test).orElse(false) // Paper - Fix swamp hut cat generation deadlock // Folia - region threading )) { if (this.structureHasPieceAt(pos, structureStart)) { return structureStart; -@@ -179,7 +166,7 @@ public class StructureManager { +@@ -179,7 +167,7 @@ public class StructureManager { } public void addReference(StructureStart structureStart) { @@ -17256,10 +17741,10 @@ index 54972cce2314eff774250101df43a9b7074e9604..0c4942895a83ce1392dd1e71a00ab6d0 } diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java -index 85d598c3354ee62f0fd1b26e485e0084967c0380..8492c8fd3ff448d559b33f27b549180918aedeea 100644 +index c02c4834ace843633b77fb43eeadd3ddc7b1f743..3f33bd3f0536676e8e8dd8e71cc247e1771311ca 100644 --- a/src/main/java/net/minecraft/world/level/block/BedBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java -@@ -365,7 +365,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock +@@ -367,7 +367,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock world.setBlock(blockposition1, (BlockState) state.setValue(BedBlock.PART, BedPart.HEAD), 3); // CraftBukkit start - SPIGOT-7315: Don't updated if we capture block states @@ -17269,38 +17754,38 @@ index 85d598c3354ee62f0fd1b26e485e0084967c0380..8492c8fd3ff448d559b33f27b5491809 } // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 29947de9eb6887f2e61516523ff08d8b581b0f53..64759367cb0dd7401d7a12517a7448d3cbca1a82 100644 +index b6d6c2cb9b227a17fb4ce42bc75f92206fbea043..fc40cad05ec033f8d2c469054f10b7ebbfdcc1d2 100644 --- a/src/main/java/net/minecraft/world/level/block/Block.java +++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -389,8 +389,8 @@ public class Block extends BlockBehaviour implements ItemLike { +@@ -382,8 +382,8 @@ public class Block extends BlockBehaviour implements ItemLike { - entityitem.setDefaultPickUpDelay(); - // CraftBukkit start -- if (world.captureDrops != null) { -- world.captureDrops.add(entityitem); -+ if (world.getCurrentWorldData().captureDrops != null) { // Folia - region threading -+ world.getCurrentWorldData().captureDrops.add(entityitem); // Folia - region threading - } else { - world.addFreshEntity(entityitem); - } + entityitem.setDefaultPickUpDelay(); + // CraftBukkit start +- if (world.captureDrops != null) { +- world.captureDrops.add(entityitem); ++ if (world.getCurrentWorldData().captureDrops != null) { // Folia - region threading ++ world.getCurrentWorldData().captureDrops.add(entityitem); // Folia - region threading + } else { + world.addFreshEntity(entityitem); + } diff --git a/src/main/java/net/minecraft/world/level/block/BushBlock.java b/src/main/java/net/minecraft/world/level/block/BushBlock.java -index a7b4b5600e3c889c69ac22294899713d50b5fe5c..08847aff604a254e82b4a7d31281953ef04462dd 100644 +index eb324fda54ada3ed7941713a784ed2d686ec8c4b..b66ff600fbad81679f1f5b6108abccabd39d84ec 100644 --- a/src/main/java/net/minecraft/world/level/block/BushBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BushBlock.java -@@ -28,7 +28,7 @@ public abstract class BushBlock extends Block { - protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) { +@@ -31,7 +31,7 @@ public abstract class BushBlock extends Block { // CraftBukkit start if (!state.canSurvive(world, pos)) { -- if (!(world instanceof net.minecraft.server.level.ServerLevel && ((net.minecraft.server.level.ServerLevel) world).hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper -+ if (!(world instanceof net.minecraft.server.level.ServerLevel && ((net.minecraft.server.level.ServerLevel) world).getCurrentWorldData().hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world, pos).isCancelled()) { // Paper // Folia - region threading + // Suppress during worldgen +- if (!(world instanceof net.minecraft.server.level.ServerLevel world1 && world1.hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world1, pos).isCancelled()) { // Paper ++ if (!(world instanceof net.minecraft.server.level.ServerLevel world1 && world1.getCurrentWorldData().hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world1, pos).isCancelled()) { // Paper // Folia - region threading return Blocks.AIR.defaultBlockState(); } } diff --git a/src/main/java/net/minecraft/world/level/block/DaylightDetectorBlock.java b/src/main/java/net/minecraft/world/level/block/DaylightDetectorBlock.java -index 26ec4838c476b8091f80aeac61db8041d5c89e88..82d333b2644c7af7137f155bfd10e03e8d7e9adc 100644 +index 7fd7f20d524fa980ed8ff8e0ca8adb9af203ccda..6f1805dd76dc7fb3a2d005672fc3a81d31824fc5 100644 --- a/src/main/java/net/minecraft/world/level/block/DaylightDetectorBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DaylightDetectorBlock.java -@@ -120,7 +120,7 @@ public class DaylightDetectorBlock extends BaseEntityBlock { +@@ -119,7 +119,7 @@ public class DaylightDetectorBlock extends BaseEntityBlock { } private static void tickEntity(Level world, BlockPos pos, BlockState state, DaylightDetectorBlockEntity blockEntity) { @@ -17310,19 +17795,19 @@ index 26ec4838c476b8091f80aeac61db8041d5c89e88..82d333b2644c7af7137f155bfd10e03e } diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -index e1021d8be840f378568f28639c259182055c78ac..640887a47048f938c3e12634207182ceba68bdcc 100644 +index 5a6c153fa2873aecba0d0d02be2cc2a514f445e3..d45b3344dfc147a725d03faab410ebe56d54ab2d 100644 --- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -@@ -51,7 +51,7 @@ public class DispenserBlock extends BaseEntityBlock { - object2objectopenhashmap.defaultReturnValue(DispenserBlock.DEFAULT_BEHAVIOR); - }); +@@ -52,7 +52,7 @@ public class DispenserBlock extends BaseEntityBlock { + private static final DefaultDispenseItemBehavior DEFAULT_BEHAVIOR = new DefaultDispenseItemBehavior(); + public static final Map DISPENSER_REGISTRY = new IdentityHashMap(); private static final int TRIGGER_DURATION = 4; - public static boolean eventFired = false; // CraftBukkit + public static ThreadLocal eventFired = ThreadLocal.withInitial(() -> Boolean.FALSE); // CraftBukkit // Folia - region threading @Override public MapCodec codec() { -@@ -110,7 +110,7 @@ public class DispenserBlock extends BaseEntityBlock { +@@ -109,7 +109,7 @@ public class DispenserBlock extends BaseEntityBlock { if (idispensebehavior != DispenseItemBehavior.NOOP) { if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(world, pos, itemstack, i)) return; // Paper - Add BlockPreDispenseEvent @@ -17332,10 +17817,10 @@ index e1021d8be840f378568f28639c259182055c78ac..640887a47048f938c3e12634207182ce } diff --git a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java -index f446c40c4d90307c568faa2866800f5326634df6..455be3cd52cf21bc37d54b8d408e458da7ae9b72 100644 +index 4fe83bd0f355549847b66afb7e61f6f2a6d97016..fa140ec5a02cb9204a498864638e2da00709dedb 100644 --- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java -@@ -102,7 +102,7 @@ public class DoublePlantBlock extends BushBlock { +@@ -104,7 +104,7 @@ public class DoublePlantBlock extends BushBlock { protected static void preventDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) { // CraftBukkit start @@ -17345,14 +17830,25 @@ index f446c40c4d90307c568faa2866800f5326634df6..455be3cd52cf21bc37d54b8d408e458d } // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java b/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java -index 3f5bb5c9ceb5b31fcc9ef0a7a6157e1e1cb2a09f..deb555743b15afcc22e694dcf1d8ceca21c0c191 100644 +index a7a21f071161fb7e73a046717d2462f871ab653c..9e3b9b61cd51299ff13587ccc8cd2a7c875d3544 100644 --- a/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java +++ b/src/main/java/net/minecraft/world/level/block/EndGatewayBlock.java -@@ -124,6 +124,29 @@ public class EndGatewayBlock extends BaseEntityBlock implements Portal { +@@ -120,9 +120,35 @@ public class EndGatewayBlock extends BaseEntityBlock implements Portal { + if (tileentity instanceof TheEndGatewayBlockEntity tileentityendgateway) { + Vec3 vec3d = tileentityendgateway.getPortalPosition(world, pos); + +- return vec3d == null ? null : (entity instanceof ThrownEnderpearl ? new TeleportTransition(world, vec3d, Vec3.ZERO, 0.0F, 0.0F, Set.of(), TeleportTransition.PLACE_PORTAL_TICKET, PlayerTeleportEvent.TeleportCause.END_GATEWAY) : new TeleportTransition(world, vec3d, Vec3.ZERO, 0.0F, 0.0F, Relative.union(Relative.DELTA, Relative.ROTATION), TeleportTransition.PLACE_PORTAL_TICKET, PlayerTeleportEvent.TeleportCause.END_GATEWAY)); // CraftBukkit ++ return vec3d == null ? null : getTeleportTransition(world, entity, vec3d); // Folia - region threading + } else { + return null; } } - ++ + // Folia start - region threading ++ public static TeleportTransition getTeleportTransition(ServerLevel world, Entity entity, Vec3 targetPos) { ++ return (entity instanceof ThrownEnderpearl ? new TeleportTransition(world, targetPos, Vec3.ZERO, 0.0F, 0.0F, Set.of(), TeleportTransition.PLACE_PORTAL_TICKET, PlayerTeleportEvent.TeleportCause.END_GATEWAY) : new TeleportTransition(world, targetPos, Vec3.ZERO, 0.0F, 0.0F, Relative.union(Relative.DELTA, Relative.ROTATION), TeleportTransition.PLACE_PORTAL_TICKET, PlayerTeleportEvent.TeleportCause.END_GATEWAY)); // CraftBukkit ++ } ++ + @Override + public boolean portalAsync(ServerLevel sourceWorld, Entity portalTarget, BlockPos portalPos) { + if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(portalTarget)) { @@ -17369,20 +17865,16 @@ index 3f5bb5c9ceb5b31fcc9ef0a7a6157e1e1cb2a09f..deb555743b15afcc22e694dcf1d8ceca + } + + return TheEndGatewayBlockEntity.teleportRegionThreading( -+ sourceWorld, portalPos, portalTarget, endGateway, EndGatewayBlock.calculateExitMovement(portalTarget), -+ DimensionTransition.PLACE_PORTAL_TICKET ++ sourceWorld, portalPos, portalTarget, endGateway, TeleportTransition.PLACE_PORTAL_TICKET + ); + } + // Folia end - region threading -+ - private static Vec3 calculateExitMovement(Entity entity) { - return entity instanceof ThrownEnderpearl ? new Vec3(0.0D, -1.0D, 0.0D) : entity.getDeltaMovement(); - } + } diff --git a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -index a35a426cc7778a51523f26057b5d61b8a3e23d5d..e1c071e0b25c4678bf08313b6c60cf895a54aa02 100644 +index 4aa14f975e1ceedf3d4a427e0daefb58b12fcafe..403cced72fa043a9084afb5bb8fa037ccb511d41 100644 --- a/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java +++ b/src/main/java/net/minecraft/world/level/block/EndPortalBlock.java -@@ -70,15 +70,7 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { +@@ -75,15 +75,7 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { world.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) return; // Paper - make cancellable // CraftBukkit end @@ -17399,7 +17891,7 @@ index a35a426cc7778a51523f26057b5d61b8a3e23d5d..e1c071e0b25c4678bf08313b6c60cf89 entity.setAsInsidePortal(this, pos); } -@@ -126,6 +118,20 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { +@@ -135,6 +127,20 @@ public class EndPortalBlock extends BaseEntityBlock implements Portal { } } @@ -17421,7 +17913,7 @@ index a35a426cc7778a51523f26057b5d61b8a3e23d5d..e1c071e0b25c4678bf08313b6c60cf89 public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { double d0 = (double) pos.getX() + random.nextDouble(); diff --git a/src/main/java/net/minecraft/world/level/block/FarmBlock.java b/src/main/java/net/minecraft/world/level/block/FarmBlock.java -index d59e33e7326489c6d55d316d0130f22235f4c63c..edb22983a17cc22ba01ee28a9ebc685aaae117eb 100644 +index c3dba0c2c94f3804338f86621dc42405e380a6b3..e979f0410a37da490f788242fa64b0bc26f75027 100644 --- a/src/main/java/net/minecraft/world/level/block/FarmBlock.java +++ b/src/main/java/net/minecraft/world/level/block/FarmBlock.java @@ -93,8 +93,8 @@ public class FarmBlock extends Block { @@ -17436,7 +17928,7 @@ index d59e33e7326489c6d55d316d0130f22235f4c63c..edb22983a17cc22ba01ee28a9ebc685a if (!FarmBlock.isNearWater(world, pos) && !world.isRainingAt(pos.above())) { if (i > 0) { diff --git a/src/main/java/net/minecraft/world/level/block/FungusBlock.java b/src/main/java/net/minecraft/world/level/block/FungusBlock.java -index 454f95ba814b375e97189430b498c0e7486fbd94..59874de6c66f48984d9ba35c6886595027259765 100644 +index ba5fff8892593a921f57cd55ad60cd6744ab4cf1..844143011fbb3453557b6cbe562ae41c7646f454 100644 --- a/src/main/java/net/minecraft/world/level/block/FungusBlock.java +++ b/src/main/java/net/minecraft/world/level/block/FungusBlock.java @@ -76,9 +76,9 @@ public class FungusBlock extends BushBlock implements BonemealableBlock { @@ -17452,10 +17944,10 @@ index 454f95ba814b375e97189430b498c0e7486fbd94..59874de6c66f48984d9ba35c68865950 // CraftBukkit end ((ConfiguredFeature) holder.value()).place(world, world.getChunkSource().getGenerator(), random, pos); diff --git a/src/main/java/net/minecraft/world/level/block/HoneyBlock.java b/src/main/java/net/minecraft/world/level/block/HoneyBlock.java -index c6f7815b5fad3aad4635208aa2e5c6739e13cb45..be52d9e56559704c7f258502b4c2919a245d2c2f 100644 +index 5c360c6768582c1a35431739613e9b406875cc21..7285dd70e73e1a15b6af6a679a1a0577afd39e44 100644 --- a/src/main/java/net/minecraft/world/level/block/HoneyBlock.java +++ b/src/main/java/net/minecraft/world/level/block/HoneyBlock.java -@@ -86,7 +86,7 @@ public class HoneyBlock extends HalfTransparentBlock { +@@ -94,7 +94,7 @@ public class HoneyBlock extends HalfTransparentBlock { } private void maybeDoSlideAchievement(Entity entity, BlockPos pos) { @@ -17465,10 +17957,10 @@ index c6f7815b5fad3aad4635208aa2e5c6739e13cb45..be52d9e56559704c7f258502b4c2919a } } diff --git a/src/main/java/net/minecraft/world/level/block/LightningRodBlock.java b/src/main/java/net/minecraft/world/level/block/LightningRodBlock.java -index a3ccd7ca5b280d4c14100bcc22c644e69262e7a3..97cef8c0d1313f0f4441cdfa96d35e9e891b2529 100644 +index a1fee00d12342cbd20e79096b405f4b108236d37..256c577e269d483ef64d1a091c36601b0a7d2293 100644 --- a/src/main/java/net/minecraft/world/level/block/LightningRodBlock.java +++ b/src/main/java/net/minecraft/world/level/block/LightningRodBlock.java -@@ -108,7 +108,7 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc +@@ -113,7 +113,7 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc @Override public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) { @@ -17478,7 +17970,7 @@ index a3ccd7ca5b280d4c14100bcc22c644e69262e7a3..97cef8c0d1313f0f4441cdfa96d35e9e } } diff --git a/src/main/java/net/minecraft/world/level/block/MushroomBlock.java b/src/main/java/net/minecraft/world/level/block/MushroomBlock.java -index 1172d85c5c26ab2142343d91149766e5993cb36a..99d42fdf822c13e8d491b665220d61579143c8e6 100644 +index 7900856c9e86afe907c00c9ac31bec93ece50abe..c0843e7a0c173a734f5eab21172b5bbb0f3d3e3e 100644 --- a/src/main/java/net/minecraft/world/level/block/MushroomBlock.java +++ b/src/main/java/net/minecraft/world/level/block/MushroomBlock.java @@ -105,7 +105,7 @@ public class MushroomBlock extends BushBlock implements BonemealableBlock { @@ -17491,10 +17983,10 @@ index 1172d85c5c26ab2142343d91149766e5993cb36a..99d42fdf822c13e8d491b665220d6157 return true; } else { diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -index 0fdbcab175b51a8b77646e0e4a267d987b133a35..c61e96d97b689ed672e4b9e350a8840d4d97d654 100644 +index 2b31bf586c1c0bd393d2aa8d0b6635dd9f22f21c..7face3645915f88e10ddaa64f97b6727c3834f15 100644 --- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -@@ -170,6 +170,33 @@ public class NetherPortalBlock extends Block implements Portal { +@@ -178,6 +178,33 @@ public class NetherPortalBlock extends Block implements Portal { } } @@ -17526,9 +18018,9 @@ index 0fdbcab175b51a8b77646e0e4a267d987b133a35..c61e96d97b689ed672e4b9e350a8840d + // Folia end - region threading + @Nullable - private DimensionTransition getExitPortal(ServerLevel worldserver, Entity entity, BlockPos blockposition, BlockPos blockposition1, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { + private TeleportTransition getExitPortal(ServerLevel worldserver, Entity entity, BlockPos blockposition, BlockPos blockposition1, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { Optional optional = worldserver.getPortalForcer().findClosestPortalPosition(blockposition1, worldborder, searchRadius); -@@ -178,10 +205,10 @@ public class NetherPortalBlock extends Block implements Portal { +@@ -186,10 +213,10 @@ public class NetherPortalBlock extends Block implements Portal { if (optional.isPresent()) { BlockPos blockposition2 = (BlockPos) optional.get(); @@ -17539,24 +18031,24 @@ index 0fdbcab175b51a8b77646e0e4a267d987b133a35..c61e96d97b689ed672e4b9e350a8840d - return worldserver.getBlockState(blockposition3) == iblockdata; + return worldserver.getBlockStateFromEmptyChunk(blockposition3) == iblockdata; // Folia - region threading }); - dimensiontransition_a = DimensionTransition.PLAY_PORTAL_SOUND.then((entity1) -> { + teleporttransition_a = TeleportTransition.PLAY_PORTAL_SOUND.then((entity1) -> { entity1.placePortalTicket(blockposition2); -@@ -227,7 +254,7 @@ public class NetherPortalBlock extends Block implements Portal { - return NetherPortalBlock.createDimensionTransition(world, exitPortalRectangle, enumdirection_enumaxis, vec3d, entity, entity.getDeltaMovement(), entity.getYRot(), entity.getXRot(), postDimensionTransition); +@@ -235,7 +262,7 @@ public class NetherPortalBlock extends Block implements Portal { + return NetherPortalBlock.createDimensionTransition(world, exitPortalRectangle, enumdirection_enumaxis, vec3d, entity, postDimensionTransition); } -- private static DimensionTransition createDimensionTransition(ServerLevel world, BlockUtil.FoundRectangle exitPortalRectangle, Direction.Axis axis, Vec3 positionInPortal, Entity entity, Vec3 velocity, float yaw, float pitch, DimensionTransition.PostDimensionTransition postDimensionTransition) { -+ public static DimensionTransition createDimensionTransition(ServerLevel world, BlockUtil.FoundRectangle exitPortalRectangle, Direction.Axis axis, Vec3 positionInPortal, Entity entity, Vec3 velocity, float yaw, float pitch, DimensionTransition.PostDimensionTransition postDimensionTransition) { // Folia - region threading - public +- private static TeleportTransition createDimensionTransition(ServerLevel world, BlockUtil.FoundRectangle exitPortalRectangle, Direction.Axis axis, Vec3 positionInPortal, Entity entity, TeleportTransition.PostTeleportTransition postDimensionTransition) { ++ public static TeleportTransition createDimensionTransition(ServerLevel world, BlockUtil.FoundRectangle exitPortalRectangle, Direction.Axis axis, Vec3 positionInPortal, Entity entity, TeleportTransition.PostTeleportTransition postDimensionTransition) { // Folia - region threading - public BlockPos blockposition = exitPortalRectangle.minCorner; BlockState iblockdata = world.getBlockState(blockposition); Direction.Axis enumdirection_enumaxis1 = (Direction.Axis) iblockdata.getOptionalValue(BlockStateProperties.HORIZONTAL_AXIS).orElse(Direction.Axis.X); diff --git a/src/main/java/net/minecraft/world/level/block/Portal.java b/src/main/java/net/minecraft/world/level/block/Portal.java -index 8ab8b76992bd4a222a9c217aba57392bf4d65d71..e2cb99c1cf5fd0468a80a3cebcb884617d0f3281 100644 +index 35ed840c1aeb56432613ec346f16f793de1c498d..fce6ae0619e9c613208ce5eda4274fee384b561b 100644 --- a/src/main/java/net/minecraft/world/level/block/Portal.java +++ b/src/main/java/net/minecraft/world/level/block/Portal.java @@ -14,6 +14,10 @@ public interface Portal { @Nullable - DimensionTransition getPortalDestination(ServerLevel world, Entity entity, BlockPos pos); + TeleportTransition getPortalDestination(ServerLevel world, Entity entity, BlockPos pos); + // Folia start - region threading + public boolean portalAsync(ServerLevel sourceWorld, Entity portalTarget, BlockPos portalPos); @@ -17566,19 +18058,19 @@ index 8ab8b76992bd4a222a9c217aba57392bf4d65d71..e2cb99c1cf5fd0468a80a3cebcb88461 return Portal.Transition.NONE; } diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java -index c131734cad123a35456d18f8a161f77a4ac9ac99..c4471342eea4f9e2b0916fc1c5f1b24bc07757fd 100644 +index 21f2c61023fadcce30452a02f067cd5d87e5d8dc..0020e7bb7b19179a898cd8835d12cfa37eccdcc2 100644 --- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java -@@ -68,7 +68,7 @@ public class RedStoneWireBlock extends Block { - }); +@@ -91,7 +91,7 @@ public class RedStoneWireBlock extends Block { private static final float PARTICLE_DENSITY = 0.2F; private final BlockState crossState; + private final RedstoneWireEvaluator evaluator = new DefaultRedstoneWireEvaluator(this); - public boolean shouldSignal = true; + //public boolean shouldSignal = true; // Folia - region threading - move to regionised world data @Override public MapCodec codec() { -@@ -260,7 +260,11 @@ public class RedStoneWireBlock extends Block { +@@ -292,7 +292,11 @@ public class RedStoneWireBlock extends Block { // Paper start - Optimize redstone (Eigencraft) // The bulk of the new functionality is found in RedstoneWireTurbo.java @@ -17591,50 +18083,37 @@ index c131734cad123a35456d18f8a161f77a4ac9ac99..c4471342eea4f9e2b0916fc1c5f1b24b /* * Modified version of pre-existing updateSurroundingRedstone, which is called from -@@ -269,7 +273,7 @@ public class RedStoneWireBlock extends Block { - */ - private void updateSurroundingRedstone(Level worldIn, BlockPos pos, BlockState state, BlockPos source) { - if (worldIn.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.EIGENCRAFT) { +@@ -308,7 +312,7 @@ public class RedStoneWireBlock extends Block { + if (orientation != null) { + source = pos.relative(orientation.getFront().getOpposite()); + } - turbo.updateSurroundingRedstone(worldIn, pos, state, source); -+ this.getTurbo(worldIn).updateSurroundingRedstone(worldIn, pos, state, source); // Folia - region threading ++ getTurbo(worldIn).updateSurroundingRedstone(worldIn, pos, state, source); // Folia - region threading return; } - updatePowerStrength(worldIn, pos, state); -@@ -288,9 +292,9 @@ public class RedStoneWireBlock extends Block { - int i = state.getValue(POWER); - int j = 0; - j = this.getPower(j, worldIn.getBlockState(pos2)); -- this.shouldSignal = false; -+ io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData().shouldSignal = false; // Folia - region threading - int k = worldIn.getBestNeighborSignal(pos1); -- this.shouldSignal = true; -+ io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData().shouldSignal = true; // Folia - region threading - - if (worldIn.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.VANILLA) { - // This code is totally redundant to if statements just below the loop. -@@ -360,7 +364,7 @@ public class RedStoneWireBlock extends Block { + updatePowerStrength(worldIn, pos, state, orientation, blockAdded); +@@ -336,7 +340,7 @@ public class RedStoneWireBlock extends Block { // [Space Walker] suppress shape updates and emit those manually to // bypass the new neighbor update stack. - if (worldIn.setBlock(pos1, state, Block.UPDATE_KNOWN_SHAPE | Block.UPDATE_CLIENTS)) -- turbo.updateNeighborShapes(worldIn, pos1, state); -+ this.getTurbo(worldIn).updateNeighborShapes(worldIn, pos1, state); // Folia - region threading + if (level.setBlock(pos, state, Block.UPDATE_KNOWN_SHAPE | Block.UPDATE_CLIENTS)) { +- turbo.updateNeighborShapes(level, pos, state); ++ this.getTurbo(level).updateNeighborShapes(level, pos, state); // Folia - region threading + } } } - -@@ -409,10 +413,10 @@ public class RedStoneWireBlock extends Block { +@@ -353,9 +357,9 @@ public class RedStoneWireBlock extends Block { } - private int calculateTargetStrength(Level world, BlockPos pos) { + public int getBlockSignal(Level world, BlockPos pos) { - this.shouldSignal = false; + io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData().shouldSignal = false; // Folia - region threading int i = world.getBestNeighborSignal(pos); - - this.shouldSignal = true; + io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData().shouldSignal = true; // Folia - region threading - int j = 0; + return i; + } - if (i < 15) { -@@ -551,12 +555,12 @@ public class RedStoneWireBlock extends Block { +@@ -449,12 +453,12 @@ public class RedStoneWireBlock extends Block { @Override protected int getDirectSignal(BlockState state, BlockGetter world, BlockPos pos, Direction direction) { @@ -17646,10 +18125,10 @@ index c131734cad123a35456d18f8a161f77a4ac9ac99..c4471342eea4f9e2b0916fc1c5f1b24b protected int getSignal(BlockState state, BlockGetter world, BlockPos pos, Direction direction) { - if (this.shouldSignal && direction != Direction.DOWN) { + if (io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData().shouldSignal && direction != Direction.DOWN) { // Folia - region threading - int i = (Integer) state.getValue(RedStoneWireBlock.POWER); - - return i == 0 ? 0 : (direction != Direction.UP && !((RedstoneSide) this.getConnectionState(world, state, pos).getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(direction.getOpposite()))).isConnected() ? 0 : i); -@@ -583,7 +587,10 @@ public class RedStoneWireBlock extends Block { + int i = state.getValue(POWER); + if (i == 0) { + return 0; +@@ -486,7 +490,10 @@ public class RedStoneWireBlock extends Block { @Override protected boolean isSignalSource(BlockState state) { @@ -17662,10 +18141,10 @@ index c131734cad123a35456d18f8a161f77a4ac9ac99..c4471342eea4f9e2b0916fc1c5f1b24b public static int getColorForPower(int powerLevel) { diff --git a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java -index ceba9617748a8b4f3a9bd459475952c9c6c9ed7c..525d3b4c0b91b87399748fceda61c4046fa6bef2 100644 +index 26319e8247e9dfa2068700d7fadc21ea5f715561..1d87310289ff28dacf3f5bfb8f3ae0593c533b25 100644 --- a/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java +++ b/src/main/java/net/minecraft/world/level/block/RedstoneTorchBlock.java -@@ -81,10 +81,10 @@ public class RedstoneTorchBlock extends BaseTorchBlock { +@@ -82,10 +82,10 @@ public class RedstoneTorchBlock extends BaseTorchBlock { protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { boolean flag = this.hasNeighborSignal(world, pos, state); // Paper start - Faster redstone torch rapid clock removal @@ -17678,7 +18157,7 @@ index ceba9617748a8b4f3a9bd459475952c9c6c9ed7c..525d3b4c0b91b87399748fceda61c404 redstoneUpdateInfos.poll(); } } -@@ -165,14 +165,14 @@ public class RedstoneTorchBlock extends BaseTorchBlock { +@@ -166,14 +166,14 @@ public class RedstoneTorchBlock extends BaseTorchBlock { private static boolean isToggledTooFrequently(Level world, BlockPos pos, boolean addNew) { // Paper start - Faster redstone torch rapid clock removal @@ -17696,7 +18175,7 @@ index ceba9617748a8b4f3a9bd459475952c9c6c9ed7c..525d3b4c0b91b87399748fceda61c404 } int i = 0; -@@ -194,12 +194,18 @@ public class RedstoneTorchBlock extends BaseTorchBlock { +@@ -200,12 +200,18 @@ public class RedstoneTorchBlock extends BaseTorchBlock { public static class Toggle { @@ -17759,7 +18238,7 @@ index d262a5a6da57ef9ba9a6fe0dfbc88f577105e74f..e842c05cfe5991ba33582b9399610aff if (treeType != null) { event = new StructureGrowEvent(location, treeType, false, null, blocks); diff --git a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java -index b7165ec19bef1a07f6618fc0429d86cda1b08da4..ad44708d19d216ed57c664940ccd1c8ecb78877c 100644 +index a94c164fbf8fc3bb7669799a53f7e5528d921e7c..01a56fe814a0c7d930c437619289e50621978697 100644 --- a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java +++ b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java @@ -54,7 +54,7 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock { @@ -17772,10 +18251,10 @@ index b7165ec19bef1a07f6618fc0429d86cda1b08da4..ad44708d19d216ed57c664940ccd1c8e final net.minecraft.world.level.chunk.ChunkAccess cachedBlockChunk = world.getChunkIfLoaded(pos); if (cachedBlockChunk == null) { // Is this needed? diff --git a/src/main/java/net/minecraft/world/level/block/WitherSkullBlock.java b/src/main/java/net/minecraft/world/level/block/WitherSkullBlock.java -index bbf59b2577812e74ffd45f694b83a42e043273c0..9d4ecf409098adbf4d47b08d7ef10c6d9c3de113 100644 +index 0fbe66cc02bd3d95c0a5dcd55380a1b4a2f17ca6..3e3fc48470cc058d84f8db3fa8dc6105eb52eb89 100644 --- a/src/main/java/net/minecraft/world/level/block/WitherSkullBlock.java +++ b/src/main/java/net/minecraft/world/level/block/WitherSkullBlock.java -@@ -61,7 +61,7 @@ public class WitherSkullBlock extends SkullBlock { +@@ -62,7 +62,7 @@ public class WitherSkullBlock extends SkullBlock { } public static void checkSpawn(Level world, BlockPos pos, SkullBlockEntity blockEntity) { @@ -17785,7 +18264,7 @@ index bbf59b2577812e74ffd45f694b83a42e043273c0..9d4ecf409098adbf4d47b08d7ef10c6d BlockState iblockdata = blockEntity.getBlockState(); boolean flag = iblockdata.is(Blocks.WITHER_SKELETON_SKULL) || iblockdata.is(Blocks.WITHER_SKELETON_WALL_SKULL); diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java -index 814e70f558d7a6186233da0ff86c94c95d390e09..412150d8f2c2604bc754ecbb04a1001932f29254 100644 +index 0e0d178f2793ab014358f534c8dc53218b89f083..7144c4dd1091edc3bbaa0f862763e3e60f520c9e 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java @@ -215,7 +215,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name @@ -17807,19 +18286,19 @@ index 814e70f558d7a6186233da0ff86c94c95d390e09..412150d8f2c2604bc754ecbb04a10019 continue; } diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 7dfabb11d3c8112f6daef35d204a2e324f4ddb5e..b7c1c8e3701fc2d67df34aaf5cebdf78e340f155 100644 +index 1f929b467a0ece3143af58a657cf5983c07a8d51..fe25d2864c0e494c6d2809cdc6adfaba67273077 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -38,7 +38,7 @@ import co.aikar.timings.MinecraftTimings; // Paper - import co.aikar.timings.Timing; // Paper +@@ -34,7 +34,7 @@ import org.bukkit.inventory.InventoryHolder; + // CraftBukkit end public abstract class BlockEntity { - static boolean ignoreTileUpdates; // Paper - Perf: Optimize Hoppers + static final ThreadLocal IGNORE_TILE_UPDATES = ThreadLocal.withInitial(() -> Boolean.FALSE); // Paper - Perf: Optimize Hoppers // Folia - region threading - public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper // CraftBukkit start - data containers -@@ -54,6 +54,12 @@ public abstract class BlockEntity { + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); +@@ -49,6 +49,12 @@ public abstract class BlockEntity { private BlockState blockState; private DataComponentMap components; @@ -17832,7 +18311,7 @@ index 7dfabb11d3c8112f6daef35d204a2e324f4ddb5e..b7c1c8e3701fc2d67df34aaf5cebdf78 public BlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { this.components = DataComponentMap.EMPTY; this.type = type; -@@ -230,7 +236,7 @@ public abstract class BlockEntity { +@@ -226,7 +232,7 @@ public abstract class BlockEntity { public void setChanged() { if (this.level != null) { @@ -17842,7 +18321,7 @@ index 7dfabb11d3c8112f6daef35d204a2e324f4ddb5e..b7c1c8e3701fc2d67df34aaf5cebdf78 } diff --git a/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java -index 6c484f3f8f37a19992ebbfe30aba399cac21acfe..47c32e2639fdb6bac0df935822fff1a54c805aa4 100644 +index a02c5feb8f2ffe6bb6070650a45762476e1ff9ac..2348dc05644bc0cfc4389051c3209a6267eae5a9 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java @@ -61,6 +61,13 @@ public class CommandBlockEntity extends BlockEntity { @@ -17860,10 +18339,10 @@ index 6c484f3f8f37a19992ebbfe30aba399cac21acfe..47c32e2639fdb6bac0df935822fff1a5 public boolean isValid() { return !CommandBlockEntity.this.isRemoved(); diff --git a/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java -index 73e532dc998e5701c1a73da846da3d3a79871b81..5e4cb998554791cdfc2e32ae7115f87e9e23feff 100644 +index d354c2ad41533ec8d52f7c5f63f8f74a0b1ce235..290db66d88061edba14fefdd261364a82624a574 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java -@@ -84,7 +84,7 @@ public class ConduitBlockEntity extends BlockEntity { +@@ -85,7 +85,7 @@ public class ConduitBlockEntity extends BlockEntity { public static void clientTick(Level world, BlockPos pos, BlockState state, ConduitBlockEntity blockEntity) { ++blockEntity.tickCount; @@ -17872,7 +18351,7 @@ index 73e532dc998e5701c1a73da846da3d3a79871b81..5e4cb998554791cdfc2e32ae7115f87e List list = blockEntity.effectBlocks; if (i % 40L == 0L) { -@@ -102,7 +102,7 @@ public class ConduitBlockEntity extends BlockEntity { +@@ -103,7 +103,7 @@ public class ConduitBlockEntity extends BlockEntity { public static void serverTick(Level world, BlockPos pos, BlockState state, ConduitBlockEntity blockEntity) { ++blockEntity.tickCount; @@ -17882,7 +18361,7 @@ index 73e532dc998e5701c1a73da846da3d3a79871b81..5e4cb998554791cdfc2e32ae7115f87e if (i % 40L == 0L) { diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index cab403efd471bb61835224eea4e99570d34dcaaa..1035a68aaeb9c50752a03cd72fe65c5eb7e8746c 100644 +index 5ebbdb94d9b91c442ff60eb6872f740ebd790fa0..44aae845da6cd34fc00e0c71795d6f610679bd4b 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java @@ -49,7 +49,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen @@ -18034,7 +18513,7 @@ index cab403efd471bb61835224eea4e99570d34dcaaa..1035a68aaeb9c50752a03cd72fe65c5e flag = true; } else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) { diff --git a/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java -index a74732902c0494c67e6acf2fc04581ff9c46b832..f543be7f11511b57d510520a531cf39cd05ddafc 100644 +index 4729befa12732a9fd65cce243b33b3b479026c41..8ad84c8fce0461457bf918b22cf55a0c47a2dbcc 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java @@ -46,9 +46,9 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi @@ -18050,7 +18529,7 @@ index a74732902c0494c67e6acf2fc04581ff9c46b832..f543be7f11511b57d510520a531cf39c @Override diff --git a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java -index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e6d85df26 100644 +index 68fd5d3f6553af8af867e34946cb8b3f852da985..cccd9a2f4d13adaf5fe677fef6f8f9db72d9d87f 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity.java @@ -39,9 +39,12 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { @@ -18067,7 +18546,7 @@ index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e public TheEndGatewayBlockEntity(BlockPos pos, BlockState state) { super(BlockEntityType.END_GATEWAY, pos, state); } -@@ -140,6 +143,103 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { +@@ -140,6 +143,104 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { } } @@ -18086,7 +18565,7 @@ index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e + this.searchingForExitId + ); + -+ ca.spottedleaf.concurrentutil.completable.Completable complete = new ca.spottedleaf.concurrentutil.completable.Completable<>(); ++ ca.spottedleaf.concurrentutil.completable.CallbackCompletable complete = new ca.spottedleaf.concurrentutil.completable.CallbackCompletable<>(); + + complete.addWaiter((tpLoc, throwable) -> { + // create the exit portal @@ -18118,8 +18597,7 @@ index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e + public static boolean teleportRegionThreading(ServerLevel portalWorld, BlockPos portalPos, + net.minecraft.world.entity.Entity toTeleport, + TheEndGatewayBlockEntity portalTile, -+ Vec3 targetSpeed, -+ net.minecraft.world.level.portal.DimensionTransition.PostDimensionTransition post) { ++ net.minecraft.world.level.portal.TeleportTransition.PostTeleportTransition post) { + // can we even teleport in this dimension? + if (portalTile.exitPortal == null && portalWorld.getTypeKey() != LevelStem.END) { + return false; @@ -18134,15 +18612,18 @@ index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e + return false; + } + ++ // note: we handle the position from the TeleportTransition ++ net.minecraft.world.level.portal.TeleportTransition teleport = net.minecraft.world.level.block.EndGatewayBlock.getTeleportTransition( ++ portalWorld, toTeleport, Vec3.atCenterOf(teleportPos) ++ ); ++ ++ + if (isExactTeleport) { + // blind teleport + return toTeleport.teleportAsync( -+ portalWorld, Vec3.atCenterOf(teleportPos), null, null, targetSpeed, -+ org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_GATEWAY, net.minecraft.world.entity.Entity.TELEPORT_FLAG_LOAD_CHUNK | net.minecraft.world.entity.Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS, -+ (net.minecraft.world.entity.Entity teleportedEntity) -> { -+ if (post != null) { -+ post.onTransition(teleportedEntity); -+ } ++ teleport, net.minecraft.world.entity.Entity.TELEPORT_FLAG_LOAD_CHUNK | net.minecraft.world.entity.Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS, ++ post == null ? null : (net.minecraft.world.entity.Entity teleportedEntity) -> { ++ post.onTransition(teleportedEntity); + } + ); + } else { @@ -18151,8 +18632,7 @@ index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e + // however, we know the target location cannot differ by one region section: so we can + // just teleport and adjust the position after + return toTeleport.teleportAsync( -+ portalWorld, Vec3.atCenterOf(teleportPos), null, null, targetSpeed, -+ org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.END_GATEWAY, net.minecraft.world.entity.Entity.TELEPORT_FLAG_LOAD_CHUNK | net.minecraft.world.entity.Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS, ++ teleport, net.minecraft.world.entity.Entity.TELEPORT_FLAG_LOAD_CHUNK | net.minecraft.world.entity.Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS, + (net.minecraft.world.entity.Entity teleportedEntity) -> { + // adjust to the final exit position + Vec3 adjusted = Vec3.atCenterOf(TheEndGatewayBlockEntity.findExitPosition(portalWorld, teleportPos)); @@ -18171,14 +18651,14 @@ index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e @Nullable public Vec3 getPortalPosition(ServerLevel world, BlockPos pos) { BlockPos blockposition1; -@@ -189,6 +289,124 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { +@@ -189,6 +290,124 @@ public class TheEndGatewayBlockEntity extends TheEndPortalBlockEntity { return TheEndGatewayBlockEntity.findTallestBlock(world, blockposition1, 16, true); } + // Folia start - region threading + private static void findOrCreateValidTeleportPosRegionThreading(ServerLevel world, BlockPos pos, -+ ca.spottedleaf.concurrentutil.completable.Completable complete) { -+ ca.spottedleaf.concurrentutil.completable.Completable tentativeSelection = new ca.spottedleaf.concurrentutil.completable.Completable<>(); ++ ca.spottedleaf.concurrentutil.completable.CallbackCompletable complete) { ++ ca.spottedleaf.concurrentutil.completable.CallbackCompletable tentativeSelection = new ca.spottedleaf.concurrentutil.completable.CallbackCompletable<>(); + + tentativeSelection.addWaiter((vec3d, throwable) -> { + LevelChunk chunk = TheEndGatewayBlockEntity.getChunk(world, vec3d); @@ -18187,8 +18667,8 @@ index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e + BlockPos blockposition2 = BlockPos.containing(vec3d.x + 0.5D, 75.0D, vec3d.z + 0.5D); + + TheEndGatewayBlockEntity.LOGGER.debug("Failed to find a suitable block to teleport to, spawning an island on {}", blockposition2); -+ world.registryAccess().registry(Registries.CONFIGURED_FEATURE).flatMap((iregistry) -> { -+ return iregistry.getHolder(EndFeatures.END_ISLAND); ++ world.registryAccess().lookup(Registries.CONFIGURED_FEATURE).flatMap((iregistry) -> { ++ return iregistry.get(EndFeatures.END_ISLAND); + }).ifPresent((holder_c) -> { + ((ConfiguredFeature) holder_c.value()).place(world, world.getChunkSource().getGenerator(), RandomSource.create(blockposition2.asLong()), blockposition2); + }); @@ -18207,7 +18687,7 @@ index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e + + BlockPos finalBlockPosition1 = blockposition1; + world.moonrise$loadChunksAsync(blockposition1, radius, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, ++ ca.spottedleaf.concurrentutil.util.Priority.NORMAL, + (java.util.List chunks) -> { + // make sure chunks are kept loaded + for (net.minecraft.world.level.chunk.ChunkAccess access : chunks) { @@ -18221,7 +18701,7 @@ index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e + io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue( + world, posX >> 4, posZ >> 4, () -> { + // find final location -+ BlockPos tpLoc = TheEndGatewayBlockEntity.findTallestBlock(world, finalBlockPosition1, radius, true); ++ BlockPos tpLoc = TheEndGatewayBlockEntity.findTallestBlock(world, finalBlockPosition1, radius, true).above(GATEWAY_HEIGHT_ABOVE_SURFACE); + + // done + complete.complete(tpLoc); @@ -18236,7 +18716,7 @@ index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e + } + + private static void findExitPortalXZPosTentativeRegionThreading(ServerLevel world, BlockPos pos, -+ ca.spottedleaf.concurrentutil.completable.Completable complete) { ++ ca.spottedleaf.concurrentutil.completable.CallbackCompletable complete) { + Vec3 posDirFromOrigin = new Vec3(pos.getX(), 0.0D, pos.getZ()).normalize(); + Vec3 posDirExtruded = posDirFromOrigin.scale(1024.0D); + @@ -18271,7 +18751,7 @@ index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e + ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(vars.currPos), + net.minecraft.world.level.chunk.status.ChunkStatus.FULL, + true, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, ++ ca.spottedleaf.concurrentutil.util.Priority.NORMAL, + (chunk) -> { + this.run(); + } @@ -18285,7 +18765,7 @@ index 89df488afeffd0c060d2d0e7fae16daf978bd192..61a40071ea6d619bee6d876a193bb79e + ca.spottedleaf.moonrise.common.util.CoordinateUtils.getChunkZ(posDirExtruded), + net.minecraft.world.level.chunk.status.ChunkStatus.FULL, + true, -+ ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, ++ ca.spottedleaf.concurrentutil.util.Priority.NORMAL, + (chunk) -> { + handle.run(); + } @@ -18308,10 +18788,10 @@ index 28e3b73507b988f7234cbf29c4024c88180d0aef..c8facee29ee08e0975528083f89b64f0 + BlockEntity getTileEntity(); // Folia - region threading } diff --git a/src/main/java/net/minecraft/world/level/block/grower/TreeGrower.java b/src/main/java/net/minecraft/world/level/block/grower/TreeGrower.java -index 597599138f69c9ee05dc7657c51c25336337875e..686986d1b1cb12b6f957c050aae3de549f49993d 100644 +index 2fec480b6ca12a95013d920852db58722579caf1..04c1803c43b6c677f4c4534b97fbc5e467f8aa5b 100644 --- a/src/main/java/net/minecraft/world/level/block/grower/TreeGrower.java +++ b/src/main/java/net/minecraft/world/level/block/grower/TreeGrower.java -@@ -174,51 +174,53 @@ public final class TreeGrower { +@@ -175,55 +175,57 @@ public final class TreeGrower { // CraftBukkit start private void setTreeType(Holder> holder) { ResourceKey> worldgentreeabstract = holder.unwrapKey().get(); @@ -18379,6 +18859,12 @@ index 597599138f69c9ee05dc7657c51c25336337875e..686986d1b1cb12b6f957c050aae3de54 } else if (worldgentreeabstract == TreeFeatures.CHERRY || worldgentreeabstract == TreeFeatures.CHERRY_BEES_005) { - SaplingBlock.treeType = TreeType.CHERRY; + treeType = TreeType.CHERRY; // Folia - region threading + } else if (worldgentreeabstract == TreeFeatures.PALE_OAK) { +- SaplingBlock.treeType = TreeType.PALE_OAK; ++ treeType = TreeType.PALE_OAK; // Folia - region threading + } else if (worldgentreeabstract == TreeFeatures.PALE_OAK_CREAKING) { +- SaplingBlock.treeType = TreeType.PALE_OAK_CREAKING; ++ treeType = TreeType.PALE_OAK_CREAKING; // Folia - region threading } else { throw new IllegalArgumentException("Unknown tree generator " + worldgentreeabstract); } @@ -18387,10 +18873,10 @@ index 597599138f69c9ee05dc7657c51c25336337875e..686986d1b1cb12b6f957c050aae3de54 // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -index e0c62227b279a5fe0f3868fbf9ce8c78c515a09c..bf9a6f40998144ba7dbdfafc8dbdbb84168d1edb 100644 +index 4b51472502d08ea357da437afeb4b581979e9cff..0a7b67863e6f75bfcde877d5d226ab60dbe5a81b 100644 --- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java +++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java -@@ -153,7 +153,7 @@ public class PistonBaseBlock extends DirectionalBlock { +@@ -156,7 +156,7 @@ public class PistonBaseBlock extends DirectionalBlock { if (tileentity instanceof PistonMovingBlockEntity) { PistonMovingBlockEntity tileentitypiston = (PistonMovingBlockEntity) tileentity; @@ -18400,10 +18886,10 @@ index e0c62227b279a5fe0f3868fbf9ce8c78c515a09c..bf9a6f40998144ba7dbdfafc8dbdbb84 } } diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -index b35f476e26a020cf75e53a5eb488717d996a6935..58b570cfdd52b414752b5a117946d59031eafe94 100644 +index e1c9a961064887070b29207efd7af47884f8dc29..c3a04ef842630b3df447dea48b84bccde0c89e83 100644 --- a/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java -@@ -40,9 +40,19 @@ public class PistonMovingBlockEntity extends BlockEntity { +@@ -41,9 +41,19 @@ public class PistonMovingBlockEntity extends BlockEntity { private static final ThreadLocal NOCLIP = ThreadLocal.withInitial(() -> null); private float progress; private float progressO; @@ -18424,7 +18910,7 @@ index b35f476e26a020cf75e53a5eb488717d996a6935..58b570cfdd52b414752b5a117946d590 public PistonMovingBlockEntity(BlockPos pos, BlockState state) { super(BlockEntityType.PISTON, pos, state); } -@@ -149,8 +159,8 @@ public class PistonMovingBlockEntity extends BlockEntity { +@@ -150,8 +160,8 @@ public class PistonMovingBlockEntity extends BlockEntity { entity.setDeltaMovement(e, g, h); // Paper - EAR items stuck in in slime pushed by a piston @@ -18435,7 +18921,7 @@ index b35f476e26a020cf75e53a5eb488717d996a6935..58b570cfdd52b414752b5a117946d590 // Paper end break; } -@@ -290,7 +300,7 @@ public class PistonMovingBlockEntity extends BlockEntity { +@@ -299,7 +309,7 @@ public class PistonMovingBlockEntity extends BlockEntity { } public static void tick(Level world, BlockPos pos, BlockState state, PistonMovingBlockEntity blockEntity) { @@ -18445,7 +18931,7 @@ index b35f476e26a020cf75e53a5eb488717d996a6935..58b570cfdd52b414752b5a117946d590 if (blockEntity.progressO >= 1.0F) { if (world.isClientSide && blockEntity.deathTicks < 5) { diff --git a/src/main/java/net/minecraft/world/level/border/WorldBorder.java b/src/main/java/net/minecraft/world/level/border/WorldBorder.java -index 04e62c54f224f7949fde9ceded208e700db55aa1..298b00641580dfab39ac9139d1ea25cec178a0d4 100644 +index 807a097a7b6399f24ede741f94ce98eb67e55add..c2a0cd1c25b6d775b55f8c3aacca9837e35a5dfd 100644 --- a/src/main/java/net/minecraft/world/level/border/WorldBorder.java +++ b/src/main/java/net/minecraft/world/level/border/WorldBorder.java @@ -34,6 +34,8 @@ public class WorldBorder { @@ -18476,7 +18962,7 @@ index 04e62c54f224f7949fde9ceded208e700db55aa1..298b00641580dfab39ac9139d1ea25ce // Paper end - Bound treasure maps to world border diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -index 488938c32a48437721a71d294c77468f00c035b9..cead18e4f8ea278b999fa0e1aff58580a6604645 100644 +index b5114f84b2df2f4606702b892d32d484225d9dcf..213d1abc8fdd7702285b6cdd85ad47ee09000d3a 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java @@ -325,7 +325,7 @@ public abstract class ChunkGenerator { @@ -18489,10 +18975,10 @@ index 488938c32a48437721a71d294c77468f00c035b9..cead18e4f8ea278b999fa0e1aff58580 return true; } else { diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..27e68ed3a508f16f53422c5aa1631b804c8eff9e 100644 +index 4640baec5bed6c2d53cc0f8ca1d273cc115abe9b..877f68f9abfc659f489d6571efc1b431e1240ed6 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -60,6 +60,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -61,6 +61,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @Override public void tick() {} @@ -18506,7 +18992,21 @@ index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..27e68ed3a508f16f53422c5aa1631b80 @Override public boolean isRemoved() { return true; -@@ -352,6 +359,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -218,12 +225,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p + + @Override + public void markUnsaved() { +- boolean flag = this.isUnsaved(); +- +- super.markUnsaved(); +- if (!flag) { +- this.unsavedListener.setUnsaved(this.chunkPos); +- } ++ super.markUnsaved(); // Folia - region threading - unsavedListener is not really used + + } + +@@ -375,6 +377,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @Nullable public BlockState setBlockState(BlockPos blockposition, BlockState iblockdata, boolean flag, boolean doPlace) { @@ -18514,7 +19014,7 @@ index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..27e68ed3a508f16f53422c5aa1631b80 // CraftBukkit end int i = blockposition.getY(); LevelChunkSection chunksection = this.getSection(this.getSectionIndex(i)); -@@ -392,7 +400,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -416,7 +419,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p boolean flag3 = iblockdata1.hasBlockEntity(); @@ -18523,7 +19023,7 @@ index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..27e68ed3a508f16f53422c5aa1631b80 iblockdata1.onRemove(this.level, blockposition, iblockdata, flag); } else if (!iblockdata1.is(block) && flag3) { this.removeBlockEntity(blockposition); -@@ -402,7 +410,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -426,7 +429,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p return null; } else { // CraftBukkit - Don't place while processing the BlockPlaceEvent, unless it's a BlockContainer. Prevents blocks such as TNT from activating when cancelled. @@ -18532,7 +19032,7 @@ index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..27e68ed3a508f16f53422c5aa1631b80 iblockdata.onPlace(this.level, blockposition, iblockdata1, flag); } -@@ -453,7 +461,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -478,7 +481,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @Nullable public BlockEntity getBlockEntity(BlockPos pos, LevelChunk.EntityCreationType creationType) { // CraftBukkit start @@ -18541,7 +19041,7 @@ index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..27e68ed3a508f16f53422c5aa1631b80 if (tileentity == null) { tileentity = (BlockEntity) this.blockEntities.get(pos); } -@@ -676,13 +684,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -700,13 +703,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p org.bukkit.World world = this.level.getWorld(); if (world != null) { @@ -18557,7 +19057,7 @@ index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..27e68ed3a508f16f53422c5aa1631b80 } } server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); -@@ -709,7 +717,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -732,7 +735,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p @Override public boolean isUnsaved() { // Paper start - rewrite chunk system @@ -18566,7 +19066,7 @@ index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..27e68ed3a508f16f53422c5aa1631b80 if (((ca.spottedleaf.moonrise.patches.chunk_system.ticks.ChunkSystemLevelChunkTicks)this.blockTicks).moonrise$isDirty(gameTime) || ((ca.spottedleaf.moonrise.patches.chunk_system.ticks.ChunkSystemLevelChunkTicks)this.fluidTicks).moonrise$isDirty(gameTime)) { return true; -@@ -980,6 +988,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -1015,6 +1018,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p this.ticker = wrapped; } @@ -18580,7 +19080,7 @@ index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..27e68ed3a508f16f53422c5aa1631b80 @Override public void tick() { this.ticker.tick(); -@@ -1016,6 +1031,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -1051,6 +1061,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p this.ticker = blockentityticker; } @@ -18594,24 +19094,11 @@ index 7c11853c5090fbc4fa5b3e73a69acf166158fdec..27e68ed3a508f16f53422c5aa1631b80 @Override public void tick() { if (!this.blockEntity.isRemoved() && this.blockEntity.hasLevel()) { -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 4bd048387651250135f963303c78c17f8473cfee..6ec9226b686e7cd9da966edc6b51d4f48dfe4d65 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -@@ -550,7 +550,7 @@ public class ChunkSerializer { - } - - private static void saveTicks(ServerLevel world, CompoundTag nbt, ChunkAccess.TicksToSave tickSchedulers) { -- long i = world.getLevelData().getGameTime(); -+ long i = world.getRedstoneGameTime(); // Folia - region threading - - nbt.put("block_ticks", tickSchedulers.blocks().save(i, (block) -> { - return BuiltInRegistries.BLOCK.getKey(block).toString(); diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -index 84300f2f7b7be4f5281edd8e263646dbcbb3ba07..b7d6547488d31a1935327f558fef84f7d55072f5 100644 +index b331c93c82c27f9456fec208a0c008c5bedfa8c4..e5513271a24711f46e9107cbe526d533afa54ca5 100644 --- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java +++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java -@@ -76,7 +76,7 @@ public class EndDragonFight { +@@ -77,7 +77,7 @@ public class EndDragonFight { private static final Component DEFAULT_BOSS_EVENT_NAME = Component.translatable("entity.minecraft.ender_dragon"); // Paper - ensure reset EnderDragon boss event name public final ServerBossEvent dragonEvent; public final ServerLevel level; @@ -18620,7 +19107,7 @@ index 84300f2f7b7be4f5281edd8e263646dbcbb3ba07..b7d6547488d31a1935327f558fef84f7 public final ObjectArrayList gateways; private final BlockPattern exitPortalPattern; private int ticksSinceDragonSeen; -@@ -154,7 +154,7 @@ public class EndDragonFight { +@@ -155,7 +155,7 @@ public class EndDragonFight { if (!this.dragonEvent.getPlayers().isEmpty()) { this.level.getChunkSource().addRegionTicket(TicketType.DRAGON, new ChunkPos(0, 0), 9, Unit.INSTANCE); @@ -18629,7 +19116,7 @@ index 84300f2f7b7be4f5281edd8e263646dbcbb3ba07..b7d6547488d31a1935327f558fef84f7 if (this.needsStateScanning && flag) { this.scanState(); -@@ -203,6 +203,12 @@ public class EndDragonFight { +@@ -204,6 +204,12 @@ public class EndDragonFight { } List list = this.level.getDragons(); @@ -18642,7 +19129,7 @@ index 84300f2f7b7be4f5281edd8e263646dbcbb3ba07..b7d6547488d31a1935327f558fef84f7 if (list.isEmpty()) { this.dragonKilled = true; -@@ -349,9 +355,8 @@ public class EndDragonFight { +@@ -350,9 +356,8 @@ public class EndDragonFight { for (int i = -8 + chunkcoordintpair.x; i <= 8 + chunkcoordintpair.x; ++i) { for (int j = 8 + chunkcoordintpair.z; j <= 8 + chunkcoordintpair.z; ++j) { @@ -18654,7 +19141,7 @@ index 84300f2f7b7be4f5281edd8e263646dbcbb3ba07..b7d6547488d31a1935327f558fef84f7 return false; } -@@ -538,6 +543,11 @@ public class EndDragonFight { +@@ -539,6 +544,11 @@ public class EndDragonFight { } public void onCrystalDestroyed(EndCrystal enderCrystal, DamageSource source) { @@ -18666,7 +19153,7 @@ index 84300f2f7b7be4f5281edd8e263646dbcbb3ba07..b7d6547488d31a1935327f558fef84f7 if (this.respawnStage != null && this.respawnCrystals.contains(enderCrystal)) { EndDragonFight.LOGGER.debug("Aborting respawn sequence"); this.respawnStage = null; -@@ -566,7 +576,7 @@ public class EndDragonFight { +@@ -569,7 +579,7 @@ public class EndDragonFight { public boolean tryRespawn(@Nullable BlockPos placedEndCrystalPos) { // placedEndCrystalPos is null if the tryRespawn() call was not caused by a placed end crystal // Paper end - Perf: Do crystal-portal proximity check before entity lookup @@ -18676,7 +19163,7 @@ index 84300f2f7b7be4f5281edd8e263646dbcbb3ba07..b7d6547488d31a1935327f558fef84f7 if (blockposition == null) { diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java -index 1741360aa3f2409b1a8ddf1d4602ffe57651a586..0788c67a09e67b9775c0d073efc72547f90df94a 100644 +index e93ef232b0426a1095dad05fc4acb2a74db5b689..6e0fafa0c8f8e91d10ec0cb71742d137e5522155 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java +++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java @@ -18,7 +18,7 @@ import net.minecraft.world.level.block.state.BlockState; @@ -18728,7 +19215,7 @@ index 1741360aa3f2409b1a8ddf1d4602ffe57651a586..0788c67a09e67b9775c0d073efc72547 if (days >= world.paperConfig().entities.behavior.pillagerPatrols.start.day && world.isDay()) { diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java -index 1b1b475ca27e799e251d6f8a8c9fe1a4fd8bae83..3085658976345d095e7c38a0edab42cb92fe5d03 100644 +index 021221da5d0315f6e371380a705ac6b3f6ac18d3..ee9a0e0ce075e932a687d77594c687384ac19fb1 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java +++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java @@ -21,7 +21,7 @@ import net.minecraft.world.level.material.FluidState; @@ -18768,7 +19255,7 @@ index 1b1b475ca27e799e251d6f8a8c9fe1a4fd8bae83..3085658976345d095e7c38a0edab42cb while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java -index b92c40352e4f1af05a2f90701b3f74c235ae57cf..8b5a88fae6afaf7da25e670f32b107f37a954714 100644 +index ff1f151b342a1567605f92a921fc7ab01f1c4807..27f428fc52cd371983c4f06329d22961ed32a15c 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java +++ b/src/main/java/net/minecraft/world/level/levelgen/feature/EndPlatformFeature.java @@ -55,7 +55,7 @@ public class EndPlatformFeature extends Feature { @@ -18781,7 +19268,7 @@ index b92c40352e4f1af05a2f90701b3f74c235ae57cf..8b5a88fae6afaf7da25e670f32b107f3 PortalCreateEvent portalEvent = new PortalCreateEvent((List) (List) blockList.getList(), bworld, entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureStart.java b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureStart.java -index c92a2c5bba1525eff39d9a3cad70fdacd426e8cb..04274f48627c40d3ac722e3ec595182d6d44b167 100644 +index d871d760581df082c47365ef246681faafb1f6a0..08e0fec629a74551a0a25990fea7ee9380a1021d 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureStart.java +++ b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureStart.java @@ -28,7 +28,7 @@ public final class StructureStart { @@ -18803,7 +19290,7 @@ index c92a2c5bba1525eff39d9a3cad70fdacd426e8cb..04274f48627c40d3ac722e3ec595182d } @@ -137,7 +137,7 @@ public final class StructureStart { - nbttagcompound.putString("id", context.registryAccess().registryOrThrow(Registries.STRUCTURE).getKey(this.structure).toString()); + nbttagcompound.putString("id", context.registryAccess().lookupOrThrow(Registries.STRUCTURE).getKey(this.structure).toString()); nbttagcompound.putInt("ChunkX", chunkPos.x); nbttagcompound.putInt("ChunkZ", chunkPos.z); - nbttagcompound.putInt("references", this.references); @@ -18845,10 +19332,10 @@ index c92a2c5bba1525eff39d9a3cad70fdacd426e8cb..04274f48627c40d3ac722e3ec595182d protected int getMaxReferences() { diff --git a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java -index 106af2b2c7ff72c7549975aef75cdcff8d9a7d97..2c9640001dba727981ad336eefade6d438eeb0ac 100644 +index 3a95e3236eafd14baed035e53503b58c2e21b68a..63b12dcb1b86e15607ebbaa157d7a330c089862d 100644 --- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java +++ b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java -@@ -48,6 +48,7 @@ public class CollectingNeighborUpdater implements NeighborUpdater { +@@ -49,6 +49,7 @@ public class CollectingNeighborUpdater implements NeighborUpdater { } private void addAndRun(BlockPos pos, CollectingNeighborUpdater.NeighborUpdates entry) { @@ -18857,43 +19344,38 @@ index 106af2b2c7ff72c7549975aef75cdcff8d9a7d97..2c9640001dba727981ad336eefade6d4 boolean bl2 = this.maxChainedNeighborUpdates >= 0 && this.count >= this.maxChainedNeighborUpdates; this.count++; diff --git a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java b/src/main/java/net/minecraft/world/level/saveddata/SavedData.java -index 4cbb943b702baaeb8bfd2b558cc848e719cf095d..6869144a2c1bb37d15f3fec622497b8d20ab2c68 100644 +index d114c62c4b0157e14fbdedebf675a53c401710ad..20da1447e036055d4c2748cc90eef15b4880e6b3 100644 --- a/src/main/java/net/minecraft/world/level/saveddata/SavedData.java +++ b/src/main/java/net/minecraft/world/level/saveddata/SavedData.java -@@ -14,7 +14,7 @@ import org.slf4j.Logger; +@@ -8,7 +8,7 @@ import net.minecraft.nbt.NbtUtils; + import net.minecraft.util.datafix.DataFixTypes; public abstract class SavedData { - private static final Logger LOGGER = LogUtils.getLogger(); - private boolean dirty; + private volatile boolean dirty; // Folia - make map data thread-safe - public abstract CompoundTag save(CompoundTag nbt, HolderLookup.Provider registryLookup); + public abstract CompoundTag save(CompoundTag nbt, HolderLookup.Provider registries); -@@ -39,6 +39,7 @@ public abstract class SavedData { - public java.util.concurrent.CompletableFuture save(File file, HolderLookup.Provider registryLookup, @org.jetbrains.annotations.Nullable java.util.concurrent.ExecutorService ioExecutor) { - // Paper end - Write SavedData IO async - if (this.isDirty()) { -+ this.setDirty(false); // Folia - make map data thread-safe - move before save, so that any changes after are not lost - CompoundTag compoundTag = new CompoundTag(); - compoundTag.put("data", this.save(new CompoundTag(), registryLookup)); - NbtUtils.addCurrentDataVersion(compoundTag); -@@ -51,7 +52,7 @@ public abstract class SavedData { - } - }; // Paper - Write SavedData IO async +@@ -26,9 +26,10 @@ public abstract class SavedData { + + public CompoundTag save(HolderLookup.Provider registries) { + CompoundTag compoundTag = new CompoundTag(); ++ this.setDirty(false); // Folia - make map data thread-safe - move before save, so that any changes after are not lost + compoundTag.put("data", this.save(new CompoundTag(), registries)); + NbtUtils.addCurrentDataVersion(compoundTag); +- this.setDirty(false); ++ // Folia - make map data thread-safe - move before save, so that any changes after are not lost + return compoundTag; + } -- this.setDirty(false); -+ // Folia - make map data thread-safe - move before save, so that any changes after are not lost - // Paper start - Write SavedData IO async - if (ioExecutor == null) { - return java.util.concurrent.CompletableFuture.runAsync(writeRunnable); // No executor, just use common pool diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapIndex.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapIndex.java -index 763b315b1d761bc3bd82d9b847ed3f64fd5ce991..7a044d337df8a14150a695d539a8e5c8799c4032 100644 +index 84f4664950e0cef7bd823bfc74f37cefce620d9e..8fb853d69691d7254abe6894a77270e844e3d9b8 100644 --- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapIndex.java +++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapIndex.java @@ -34,17 +34,21 @@ public class MapIndex extends SavedData { @Override - public CompoundTag save(CompoundTag nbt, HolderLookup.Provider registryLookup) { + public CompoundTag save(CompoundTag nbt, HolderLookup.Provider registries) { + synchronized (this.usedAuxIds) { // Folia - make map data thread-safe for (Entry entry : this.usedAuxIds.object2IntEntrySet()) { nbt.putInt(entry.getKey(), entry.getIntValue()); @@ -18913,15 +19395,15 @@ index 763b315b1d761bc3bd82d9b847ed3f64fd5ce991..7a044d337df8a14150a695d539a8e5c8 } } diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9f0476a6b 100644 +index ae321b3b8d98e42ef07fd1f0f738c1a2b428f6db..ed258986f2bdec9f78aa41d7dc49a5ec14094c57 100644 --- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java @@ -212,7 +212,7 @@ public class MapItemSavedData extends SavedData { } @Override -- public CompoundTag save(CompoundTag nbt, HolderLookup.Provider registryLookup) { -+ public synchronized CompoundTag save(CompoundTag nbt, HolderLookup.Provider registryLookup) { // Folia - make map data thread-safe +- public CompoundTag save(CompoundTag nbt, HolderLookup.Provider registries) { ++ public synchronized CompoundTag save(CompoundTag nbt, HolderLookup.Provider registries) { // Folia - make map data thread-safe DataResult dataresult = ResourceLocation.CODEC.encodeStart(NbtOps.INSTANCE, this.dimension.location()); // CraftBukkit - decompile error Logger logger = MapItemSavedData.LOGGER; @@ -18934,7 +19416,7 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 MapItemSavedData worldmap = new MapItemSavedData(this.centerX, this.centerZ, this.scale, this.trackingPosition, this.unlimitedTracking, true, this.dimension); worldmap.bannerMarkers.putAll(this.bannerMarkers); -@@ -273,7 +273,7 @@ public class MapItemSavedData extends SavedData { +@@ -272,7 +272,7 @@ public class MapItemSavedData extends SavedData { return worldmap; } @@ -18943,7 +19425,7 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 return MapItemSavedData.createFresh((double) this.centerX, (double) this.centerZ, (byte) Mth.clamp(this.scale + 1, 0, 4), this.trackingPosition, this.unlimitedTracking, this.dimension); } -@@ -285,7 +285,8 @@ public class MapItemSavedData extends SavedData { +@@ -284,7 +284,8 @@ public class MapItemSavedData extends SavedData { }; } @@ -18953,16 +19435,16 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 if (!this.carriedByPlayers.containsKey(player)) { MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = new MapItemSavedData.HoldingPlayer(player); -@@ -379,7 +380,7 @@ public class MapItemSavedData extends SavedData { - rotation += rotation < 0.0D ? -8.0D : 8.0D; - b2 = (byte) ((int) (rotation * 16.0D / 360.0D)); - if (this.dimension == Level.NETHER && world != null) { -- int j = (int) (world.getLevelData().getDayTime() / 10L); -+ int j = (int) (world.getLevelData().getDayTime() / 10L); // Folia - region threading - TODO +@@ -439,7 +440,7 @@ public class MapItemSavedData extends SavedData { - b2 = (byte) (j * j * 34187121 + j * 121 >> 15 & 15); - } -@@ -438,14 +439,14 @@ public class MapItemSavedData extends SavedData { + private byte calculateRotation(@Nullable LevelAccessor world, double rotation) { + if (this.dimension == Level.NETHER && world != null) { +- int i = (int) (world.getLevelData().getDayTime() / 10L); ++ int i = (int) (world.dayTime() / 10L); // Folia - region threading + + return (byte) (i * i * 34187121 + i * 121 >> 15 & 15); + } else { +@@ -470,14 +471,14 @@ public class MapItemSavedData extends SavedData { } @Nullable @@ -18980,7 +19462,7 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 Iterator iterator = this.carriedBy.iterator(); while (iterator.hasNext()) { -@@ -453,15 +454,16 @@ public class MapItemSavedData extends SavedData { +@@ -485,15 +486,16 @@ public class MapItemSavedData extends SavedData { worldmap_worldmaphumantracker.markColorsDirty(x, z); } @@ -19001,7 +19483,7 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 MapItemSavedData.HoldingPlayer worldmap_worldmaphumantracker = (MapItemSavedData.HoldingPlayer) this.carriedByPlayers.get(player); if (worldmap_worldmaphumantracker == null) { -@@ -473,7 +475,7 @@ public class MapItemSavedData extends SavedData { +@@ -505,7 +507,7 @@ public class MapItemSavedData extends SavedData { return worldmap_worldmaphumantracker; } @@ -19010,7 +19492,7 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 double d0 = (double) pos.getX() + 0.5D; double d1 = (double) pos.getZ() + 0.5D; int i = 1 << this.scale; -@@ -482,7 +484,7 @@ public class MapItemSavedData extends SavedData { +@@ -514,7 +516,7 @@ public class MapItemSavedData extends SavedData { boolean flag = true; if (d2 >= -63.0D && d3 >= -63.0D && d2 <= 63.0D && d3 <= 63.0D) { @@ -19019,7 +19501,7 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 if (mapiconbanner == null) { return false; -@@ -503,7 +505,7 @@ public class MapItemSavedData extends SavedData { +@@ -535,7 +537,7 @@ public class MapItemSavedData extends SavedData { return false; } @@ -19028,7 +19510,7 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 Iterator iterator = this.bannerMarkers.values().iterator(); while (iterator.hasNext()) { -@@ -525,12 +527,12 @@ public class MapItemSavedData extends SavedData { +@@ -557,13 +559,13 @@ public class MapItemSavedData extends SavedData { return this.bannerMarkers.values(); } @@ -19036,6 +19518,7 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 + public synchronized void removedFromFrame(BlockPos pos, int id) { // Folia - make map data thread-safe this.removeDecoration(MapItemSavedData.getFrameKey(id)); this.frameMarkers.remove(MapFrame.frameId(pos)); + this.setDirty(); } - public boolean updateColor(int x, int z, byte color) { @@ -19043,7 +19526,7 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 byte b1 = this.colors[x + z * 128]; if (b1 != color) { -@@ -541,12 +543,12 @@ public class MapItemSavedData extends SavedData { +@@ -574,12 +576,12 @@ public class MapItemSavedData extends SavedData { } } @@ -19058,7 +19541,16 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 Iterator iterator = this.decorations.values().iterator(); MapDecoration mapicon; -@@ -581,7 +583,7 @@ public class MapItemSavedData extends SavedData { +@@ -595,7 +597,7 @@ public class MapItemSavedData extends SavedData { + return true; + } + +- public void addClientSideDecorations(List decorations) { ++ public synchronized void addClientSideDecorations(List decorations) { // Folia - make map data thread-safe + this.decorations.clear(); + this.trackedDecorationCount = 0; + +@@ -614,7 +616,7 @@ public class MapItemSavedData extends SavedData { return this.decorations.values(); } @@ -19067,7 +19559,7 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 return this.trackedDecorationCount >= decorationCount; } -@@ -729,11 +731,13 @@ public class MapItemSavedData extends SavedData { +@@ -766,11 +768,13 @@ public class MapItemSavedData extends SavedData { } public void applyToMap(MapItemSavedData mapState) { @@ -19082,10 +19574,10 @@ index 6794466051dd4b725d579b2136c37844995a648e..9af0c40e5509b10775c51014f6f739a9 } } diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -index 6e23e69abd56eeda3b52a22019e1b74ae10682e7..2c086f1d4cbfc29a759a77e5c5f9f39d177e81ba 100644 +index d16f124e0371ce943298c8d7d9bfac21e98cf885..01ad37205191cc26d616e16b2ef71666711f218d 100644 --- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java -@@ -43,6 +43,7 @@ public class DimensionDataStorage implements java.io.Closeable { // Paper - Writ +@@ -46,6 +46,7 @@ public class DimensionDataStorage implements AutoCloseable { } public T computeIfAbsent(SavedData.Factory type, String id) { @@ -19093,7 +19585,7 @@ index 6e23e69abd56eeda3b52a22019e1b74ae10682e7..2c086f1d4cbfc29a759a77e5c5f9f39d T savedData = this.get(type, id); if (savedData != null) { return savedData; -@@ -51,10 +52,12 @@ public class DimensionDataStorage implements java.io.Closeable { // Paper - Writ +@@ -54,10 +55,12 @@ public class DimensionDataStorage implements AutoCloseable { this.set(id, savedData2); return savedData2; } @@ -19103,32 +19595,33 @@ index 6e23e69abd56eeda3b52a22019e1b74ae10682e7..2c086f1d4cbfc29a759a77e5c5f9f39d @Nullable public T get(SavedData.Factory type, String id) { + synchronized (this.cache) { // Folia - make map data thread-safe - SavedData savedData = this.cache.get(id); - if (savedData == null && !this.cache.containsKey(id)) { - savedData = this.readSavedData(type.deserializer(), type.type(), id); -@@ -62,6 +65,7 @@ public class DimensionDataStorage implements java.io.Closeable { // Paper - Writ + Optional optional = this.cache.get(id); + if (optional == null) { + optional = Optional.ofNullable(this.readSavedData(type.deserializer(), type.type(), id)); +@@ -65,6 +68,7 @@ public class DimensionDataStorage implements AutoCloseable { } - return (T)savedData; + return (T)optional.orElse(null); + } // Folia - make map data thread-safe } @Nullable -@@ -80,7 +84,9 @@ public class DimensionDataStorage implements java.io.Closeable { // Paper - Writ +@@ -83,8 +87,10 @@ public class DimensionDataStorage implements AutoCloseable { } public void set(String id, SavedData state) { + synchronized (this.cache) { // Folia - make map data thread-safe - this.cache.put(id, state); + this.cache.put(id, Optional.of(state)); + state.setDirty(); + } // Folia - make map data thread-safe } public CompoundTag readTagFromDisk(String id, DataFixTypes dataFixTypes, int currentSaveVersion) throws IOException { diff --git a/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java b/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java -index c42c0d1e4da30aa15f32d4ca524aeabd26fc50cf..e328d3d22d19b5dd1507c40119801fcfc3289e67 100644 +index 3858c83c58e78435a6e29de84c33faa2f26d593d..4af07bd98b6bdb056b2e1138a9f9fc3dada725df 100644 --- a/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java +++ b/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java -@@ -49,6 +49,21 @@ public class LevelChunkTicks implements SerializableTickContainer, TickCon +@@ -48,6 +48,21 @@ public class LevelChunkTicks implements SerializableTickContainer, TickCon this.dirty = false; } // Paper end - rewrite chunk system @@ -19151,10 +19644,10 @@ index c42c0d1e4da30aa15f32d4ca524aeabd26fc50cf..e328d3d22d19b5dd1507c40119801fcf public LevelChunkTicks() { } diff --git a/src/main/java/net/minecraft/world/ticks/LevelTicks.java b/src/main/java/net/minecraft/world/ticks/LevelTicks.java -index 7a69564572357a7acc043e35b9c113beeb738951..ea161048b68de3c8cdcba5f4cb66eb1531364b2e 100644 +index 778e6476c86d823dc8efe603a95e589e8b2ea9d9..3fc6b4f93885fe447ed068bc5e0784daad655696 100644 --- a/src/main/java/net/minecraft/world/ticks/LevelTicks.java +++ b/src/main/java/net/minecraft/world/ticks/LevelTicks.java -@@ -39,12 +39,69 @@ public class LevelTicks implements LevelTickAccess { +@@ -38,12 +38,69 @@ public class LevelTicks implements LevelTickAccess { private final List> alreadyRunThisTick = new ArrayList<>(); private final Set> toRunThisTickSet = new ObjectOpenCustomHashSet<>(ScheduledTick.UNIQUE_TICK_HASH); private final BiConsumer, ScheduledTick> chunkScheduleUpdater = (chunkTickScheduler, tick) -> { @@ -19165,7 +19658,7 @@ index 7a69564572357a7acc043e35b9c113beeb738951..ea161048b68de3c8cdcba5f4cb66eb15 } }; -- public LevelTicks(LongPredicate tickingFutureReadyPredicate, Supplier profilerGetter) { +- public LevelTicks(LongPredicate tickingFutureReadyPredicate) { + // Folia start - region threading + public final net.minecraft.server.level.ServerLevel world; + public final boolean isBlock; @@ -19223,11 +19716,11 @@ index 7a69564572357a7acc043e35b9c113beeb738951..ea161048b68de3c8cdcba5f4cb66eb15 + } + // Folia end - region threading + -+ public LevelTicks(LongPredicate tickingFutureReadyPredicate, Supplier profilerGetter, net.minecraft.server.level.ServerLevel world, boolean isBlock) { this.world = world; this.isBlock = isBlock; // Folia - add world and isBlock ++ public LevelTicks(LongPredicate tickingFutureReadyPredicate, net.minecraft.server.level.ServerLevel world, boolean isBlock) { this.world = world; this.isBlock = isBlock; // Folia - add world and isBlock this.tickCheck = tickingFutureReadyPredicate; - this.profiler = profilerGetter; } -@@ -57,7 +114,17 @@ public class LevelTicks implements LevelTickAccess { + +@@ -55,7 +112,17 @@ public class LevelTicks implements LevelTickAccess { this.nextTickForContainer.put(l, scheduledTick.triggerTick()); } @@ -19246,7 +19739,7 @@ index 7a69564572357a7acc043e35b9c113beeb738951..ea161048b68de3c8cdcba5f4cb66eb15 } public void removeContainer(ChunkPos pos) { -@@ -71,6 +138,7 @@ public class LevelTicks implements LevelTickAccess { +@@ -69,6 +136,7 @@ public class LevelTicks implements LevelTickAccess { @Override public void schedule(ScheduledTick orderedTick) { @@ -19255,10 +19748,10 @@ index 7a69564572357a7acc043e35b9c113beeb738951..ea161048b68de3c8cdcba5f4cb66eb15 LevelChunkTicks levelChunkTicks = this.allContainers.get(l); if (levelChunkTicks == null) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..f9b399214848098149eb1f3a4043028d242dd454 100644 +index ac8af406180bc680d46e8edc3da0fc2e5211345a..7cc63a4a9759d3926f843cfedbc79986d1ece926 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -312,7 +312,7 @@ public final class CraftServer implements Server { +@@ -315,7 +315,7 @@ public final class CraftServer implements Server { public final io.papermc.paper.SparksFly spark; // Paper - spark // Paper start - Folia region threading API @@ -19267,20 +19760,16 @@ index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..f9b399214848098149eb1f3a4043028d private final io.papermc.paper.threadedregions.scheduler.FoliaAsyncScheduler asyncScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaAsyncScheduler(); private final io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler globalRegionScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler(); -@@ -380,6 +380,12 @@ public final class CraftServer implements Server { - return ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandleRaw()); +@@ -392,7 +392,7 @@ public final class CraftServer implements Server { + + @Override + public final boolean isGlobalTickThread() { +- return ca.spottedleaf.moonrise.common.util.TickThread.isTickThread(); ++ return io.papermc.paper.threadedregions.RegionizedServer.isGlobalTickThread(); // Folia - region threading API } // Paper end - Folia reagion threading API -+ // Folia start - region threading API -+ @Override -+ public boolean isGlobalTickThread() { -+ return io.papermc.paper.threadedregions.RegionizedServer.isGlobalTickThread(); -+ } -+ // Folia end - region threading API - static { - ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); -@@ -973,6 +979,9 @@ public final class CraftServer implements Server { +@@ -987,6 +987,9 @@ public final class CraftServer implements Server { // NOTE: Should only be called from DedicatedServer.ah() public boolean dispatchServerCommand(CommandSender sender, ConsoleInput serverCommand) { @@ -19290,7 +19779,7 @@ index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..f9b399214848098149eb1f3a4043028d if (sender instanceof Conversable) { Conversable conversable = (Conversable) sender; -@@ -992,12 +1001,46 @@ public final class CraftServer implements Server { +@@ -1006,12 +1009,46 @@ public final class CraftServer implements Server { } } @@ -19337,7 +19826,7 @@ index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..f9b399214848098149eb1f3a4043028d if (this.commandMap.dispatch(sender, commandLine)) { return true; } -@@ -3193,7 +3236,7 @@ public final class CraftServer implements Server { +@@ -3234,7 +3271,7 @@ public final class CraftServer implements Server { @Override public int getCurrentTick() { @@ -19347,10 +19836,10 @@ index c7df339aeb62ee627edaf1bb4c8474b61e357ba6..f9b399214848098149eb1f3a4043028d @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab647ae7cb8 100644 +index 8f234b46c24a0ae08aa5f8190c5b27e1f62dfbab..e255a8e1a3c07d62fae6589b45f9f873ef4f7568 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -227,7 +227,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -231,7 +231,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public int getTickableTileEntityCount() { @@ -19359,7 +19848,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 } @Override -@@ -302,7 +302,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -298,7 +298,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { // Paper start - per world spawn limits for (SpawnCategory spawnCategory : SpawnCategory.values()) { if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { @@ -19368,24 +19857,15 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 } } // Paper end - per world spawn limits -@@ -372,6 +372,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -368,6 +368,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public Chunk getChunkAt(int x, int z) { -+ ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.getHandle(), x, z); // Folia - region threading ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.getHandle(), x, z, "Async chunk retrieval"); // Folia - region threading warnUnsafeChunk("getting a faraway chunk", x, z); // Paper - // Paper start - add ticket to hold chunk for a little while longer if plugin accesses it - net.minecraft.world.level.chunk.LevelChunk chunk = this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); -@@ -395,7 +396,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { - - // Paper start - private void addTicket(int x, int z) { -- io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> this.world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE)); // Paper -+ this.world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE); // Paper // Folia - region threading - does not need to be on the main thread anymore - } - // Paper end - -@@ -414,10 +415,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { + net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) this.world.getChunk(x, z, ChunkStatus.FULL, true); + return new CraftChunk(chunk); +@@ -398,10 +399,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean isChunkGenerated(int x, int z) { // Paper start - Fix this method @@ -19398,7 +19878,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 } ChunkAccess chunk = world.getChunkSource().getChunkAtImmediately(x, z); if (chunk != null) { -@@ -474,7 +475,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -458,7 +459,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { } private boolean unloadChunk0(int x, int z, boolean save) { @@ -19407,7 +19887,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 if (!this.isChunkLoaded(x, z)) { return true; } -@@ -489,7 +490,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -475,7 +476,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean regenerateChunk(int x, int z) { @@ -19416,7 +19896,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 throw new UnsupportedOperationException("Not supported in this Minecraft version! Unless you can fix it, this is not a bug :)"); /* if (!unloadChunk0(x, z, false)) { -@@ -516,6 +517,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -502,6 +503,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean refreshChunk(int x, int z) { @@ -19424,7 +19904,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); if (playerChunk == null) return false; -@@ -576,7 +578,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -562,7 +564,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean loadChunk(int x, int z, boolean generate) { @@ -19433,7 +19913,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 warnUnsafeChunk("loading a faraway chunk", x, z); // Paper ChunkAccess chunk = this.world.getChunkSource().getChunk(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper -@@ -617,7 +619,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -603,7 +605,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { DistanceManager chunkDistanceManager = this.world.getChunkSource().chunkMap.distanceManager; if (chunkDistanceManager.addRegionTicketAtDistance(TicketType.PLUGIN_TICKET, new ChunkPos(x, z), 2, plugin)) { // keep in-line with force loading, add at level 31 @@ -19442,7 +19922,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 return true; } -@@ -828,13 +830,15 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -814,13 +816,15 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) { @@ -19463,7 +19943,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 BlockPos position = ((CraftBlockState) blockstate).getPosition(); net.minecraft.world.level.block.state.BlockState oldBlock = this.world.getBlockState(position); int flag = ((CraftBlockState) blockstate).getFlag(); -@@ -842,10 +846,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -828,10 +832,10 @@ public class CraftWorld extends CraftRegionAccessor implements World { net.minecraft.world.level.block.state.BlockState newBlock = this.world.getBlockState(position); this.world.notifyAndUpdatePhysics(position, null, oldBlock, newBlock, newBlock, flag, 512); } @@ -19476,7 +19956,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 return false; } } -@@ -879,6 +883,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -865,6 +869,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setTime(long time) { @@ -19484,7 +19964,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 long margin = (time - this.getFullTime()) % 24000; if (margin < 0) margin += 24000; this.setFullTime(this.getFullTime() + margin); -@@ -891,6 +896,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -877,6 +882,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setFullTime(long time) { @@ -19492,7 +19972,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 // Notify anyone who's listening TimeSkipEvent event = new TimeSkipEvent(this, TimeSkipEvent.SkipReason.CUSTOM, time - this.world.getDayTime()); this.server.getPluginManager().callEvent(event); -@@ -918,7 +924,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -904,7 +910,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public long getGameTime() { @@ -19501,21 +19981,23 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 } @Override -@@ -947,11 +953,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -929,6 +935,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { + } + public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source, Consumer configurator) { + // Paper end - expand explosion API ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot create explosion asynchronously"); // Folia - region threading + net.minecraft.world.level.Level.ExplosionInteraction explosionType; + if (!breakBlocks) { + explosionType = net.minecraft.world.level.Level.ExplosionInteraction.NONE; // Don't break blocks +@@ -938,6 +945,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { explosionType = net.minecraft.world.level.Level.ExplosionInteraction.MOB; // Respect mobGriefing gamerule } + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, x, z, "Cannot create explosion asynchronously"); // Folia - region threading - return !this.world.explode(source == null ? null : ((CraftEntity) source).getHandle(), x, y, z, power, setFire, explosionType).wasCanceled; + net.minecraft.world.entity.Entity entity = (source == null) ? null : ((CraftEntity) source).getHandle(); + return !this.world.explode0(entity, Explosion.getDefaultDamageSource(this.world, entity), null, x, y, z, power, setFire, explosionType, ParticleTypes.EXPLOSION, ParticleTypes.EXPLOSION_EMITTER, SoundEvents.GENERIC_EXPLODE, configurator).wasCanceled; // Paper - expand explosion API } - // Paper start - @Override - public boolean createExplosion(Entity source, Location loc, float power, boolean setFire, boolean breakBlocks, boolean excludeSourceFromDamage) { -+ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, loc.getX(), loc.getZ(), "Cannot create explosion asynchronously"); // Folia - region threading - return !world.explode(source != null ? ((org.bukkit.craftbukkit.entity.CraftEntity) source).getHandle() : null, loc.getX(), loc.getY(), loc.getZ(), power, setFire, breakBlocks ? net.minecraft.world.level.Level.ExplosionInteraction.MOB : net.minecraft.world.level.Level.ExplosionInteraction.NONE, explosion -> { - explosion.excludeSourceFromDamage = excludeSourceFromDamage; - }).wasCanceled; -@@ -1030,6 +1038,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1020,6 +1028,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public int getHighestBlockYAt(int x, int z, org.bukkit.HeightMap heightMap) { @@ -19523,7 +20005,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 warnUnsafeChunk("getting a faraway chunk", x >> 4, z >> 4); // Paper // Transient load for this tick return this.world.getChunk(x >> 4, z >> 4).getHeight(CraftHeightMap.toNMS(heightMap), x, z); -@@ -1060,6 +1069,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1050,6 +1059,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setBiome(int x, int y, int z, Holder bb) { BlockPos pos = new BlockPos(x, 0, z); @@ -19531,7 +20013,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 if (this.world.hasChunkAt(pos)) { net.minecraft.world.level.chunk.LevelChunk chunk = this.world.getChunkAt(pos); -@@ -1370,6 +1380,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1360,6 +1370,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setStorm(boolean hasStorm) { @@ -19539,7 +20021,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.world.serverLevelData.setRaining(hasStorm, org.bukkit.event.weather.WeatherChangeEvent.Cause.PLUGIN); // Paper - Add cause to Weather/ThunderChangeEvents this.setWeatherDuration(0); // Reset weather duration (legacy behaviour) this.setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) -@@ -1382,6 +1393,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1372,6 +1383,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setWeatherDuration(int duration) { @@ -19547,7 +20029,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.world.serverLevelData.setRainTime(duration); } -@@ -1392,6 +1404,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1382,6 +1394,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setThundering(boolean thundering) { @@ -19555,7 +20037,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.world.serverLevelData.setThundering(thundering, org.bukkit.event.weather.ThunderChangeEvent.Cause.PLUGIN); // Paper - Add cause to Weather/ThunderChangeEvents this.setThunderDuration(0); // Reset weather duration (legacy behaviour) this.setClearWeatherDuration(0); // Reset clear weather duration (reset "/weather clear" commands) -@@ -1404,6 +1417,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1394,6 +1407,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setThunderDuration(int duration) { @@ -19563,7 +20045,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.world.serverLevelData.setThunderTime(duration); } -@@ -1414,6 +1428,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1404,6 +1418,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setClearWeatherDuration(int duration) { @@ -19571,7 +20053,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.world.serverLevelData.setClearWeatherTime(duration); } -@@ -1608,6 +1623,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1598,6 +1613,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setKeepSpawnInMemory(boolean keepLoaded) { @@ -19579,7 +20061,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 if (keepLoaded) { this.setGameRule(GameRule.SPAWN_CHUNK_RADIUS, this.getGameRuleDefault(GameRule.SPAWN_CHUNK_RADIUS)); } else { -@@ -1676,6 +1692,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1666,6 +1682,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setHardcore(boolean hardcore) { @@ -19587,7 +20069,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.world.serverLevelData.settings.hardcore = hardcore; } -@@ -1688,6 +1705,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1678,6 +1695,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerAnimalSpawns(int ticksPerAnimalSpawns) { @@ -19595,7 +20077,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.setTicksPerSpawns(SpawnCategory.ANIMAL, ticksPerAnimalSpawns); } -@@ -1700,6 +1718,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1690,6 +1708,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerMonsterSpawns(int ticksPerMonsterSpawns) { @@ -19603,7 +20085,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.setTicksPerSpawns(SpawnCategory.MONSTER, ticksPerMonsterSpawns); } -@@ -1712,6 +1731,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1702,6 +1721,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerWaterSpawns(int ticksPerWaterSpawns) { @@ -19611,7 +20093,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.setTicksPerSpawns(SpawnCategory.WATER_ANIMAL, ticksPerWaterSpawns); } -@@ -1724,6 +1744,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1714,6 +1734,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerWaterAmbientSpawns(int ticksPerWaterAmbientSpawns) { @@ -19619,7 +20101,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.setTicksPerSpawns(SpawnCategory.WATER_AMBIENT, ticksPerWaterAmbientSpawns); } -@@ -1736,6 +1757,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1726,6 +1747,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerWaterUndergroundCreatureSpawns(int ticksPerWaterUndergroundCreatureSpawns) { @@ -19627,7 +20109,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.setTicksPerSpawns(SpawnCategory.WATER_UNDERGROUND_CREATURE, ticksPerWaterUndergroundCreatureSpawns); } -@@ -1748,11 +1770,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1738,11 +1760,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setTicksPerAmbientSpawns(int ticksPerAmbientSpawns) { @@ -19641,7 +20123,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null"); Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory.%s are not supported", spawnCategory); -@@ -1769,21 +1793,25 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1759,21 +1783,25 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setMetadata(String metadataKey, MetadataValue newMetadataValue) { @@ -19667,7 +20149,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.server.getWorldMetadata().removeMetadata(this, metadataKey, owningPlugin); } -@@ -1796,6 +1824,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1786,6 +1814,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setMonsterSpawnLimit(int limit) { @@ -19675,7 +20157,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.setSpawnLimit(SpawnCategory.MONSTER, limit); } -@@ -1808,6 +1837,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1798,6 +1827,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setAnimalSpawnLimit(int limit) { @@ -19683,7 +20165,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.setSpawnLimit(SpawnCategory.ANIMAL, limit); } -@@ -1820,6 +1850,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1810,6 +1840,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setWaterAnimalSpawnLimit(int limit) { @@ -19691,7 +20173,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.setSpawnLimit(SpawnCategory.WATER_ANIMAL, limit); } -@@ -1832,6 +1863,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1822,6 +1853,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setWaterAmbientSpawnLimit(int limit) { @@ -19699,7 +20181,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.setSpawnLimit(SpawnCategory.WATER_AMBIENT, limit); } -@@ -1844,6 +1876,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1834,6 +1866,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setWaterUndergroundCreatureSpawnLimit(int limit) { @@ -19707,7 +20189,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.setSpawnLimit(SpawnCategory.WATER_UNDERGROUND_CREATURE, limit); } -@@ -1856,6 +1889,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1846,6 +1879,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override @Deprecated public void setAmbientSpawnLimit(int limit) { @@ -19715,7 +20197,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 this.setSpawnLimit(SpawnCategory.AMBIENT, limit); } -@@ -1878,6 +1912,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1868,6 +1902,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setSpawnLimit(SpawnCategory spawnCategory, int limit) { @@ -19723,7 +20205,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null"); Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory.%s are not supported", spawnCategory); -@@ -1960,7 +1995,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1950,7 +1985,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { if (!(entity instanceof CraftEntity craftEntity) || entity.getWorld() != this || sound == null || category == null) return; ClientboundSoundEntityPacket packet = new ClientboundSoundEntityPacket(CraftSound.bukkitToMinecraftHolder(sound), net.minecraft.sounds.SoundSource.valueOf(category.name()), craftEntity.getHandle(), volume, pitch, seed); @@ -19732,7 +20214,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 if (entityTracker != null) { entityTracker.broadcastAndSend(packet); } -@@ -1972,7 +2007,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1971,7 +2006,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { if (!(entity instanceof CraftEntity craftEntity) || entity.getWorld() != this || sound == null || category == null) return; ClientboundSoundEntityPacket packet = new ClientboundSoundEntityPacket(Holder.direct(SoundEvent.createVariableRangeEvent(ResourceLocation.parse(sound))), net.minecraft.sounds.SoundSource.valueOf(category.name()), craftEntity.getHandle(), volume, pitch, seed); @@ -19741,7 +20223,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 if (entityTracker != null) { entityTracker.broadcastAndSend(packet); } -@@ -2061,6 +2096,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2054,6 +2089,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean setGameRuleValue(String rule, String value) { @@ -19749,7 +20231,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 // No null values allowed if (rule == null || value == null) return false; -@@ -2103,6 +2139,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2096,6 +2132,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean setGameRule(GameRule rule, T newValue) { @@ -19757,7 +20239,7 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 Preconditions.checkArgument(rule != null, "GameRule cannot be null"); Preconditions.checkArgument(newValue != null, "GameRule value cannot be null"); -@@ -2329,6 +2366,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2322,6 +2359,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void sendGameEvent(Entity sourceEntity, org.bukkit.GameEvent gameEvent, Vector position) { @@ -19767,29 +20249,11 @@ index e76186d580a2d7f1a83af4600b0bdd435b67eba3..e6e83eb3974f0963916b36281b5e2ab6 + } + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.world, position.getX(), position.getZ(), "Cannot send game event asynchronously"); + // Folia end - region threading - getHandle().gameEvent(sourceEntity != null ? ((CraftEntity) sourceEntity).getHandle(): null, net.minecraft.core.registries.BuiltInRegistries.GAME_EVENT.getHolder(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(gameEvent.getKey())).orElseThrow(), org.bukkit.craftbukkit.util.CraftVector.toBlockPos(position)); + getHandle().gameEvent(sourceEntity != null ? ((CraftEntity) sourceEntity).getHandle(): null, net.minecraft.core.registries.BuiltInRegistries.GAME_EVENT.get(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(gameEvent.getKey())).orElseThrow(), org.bukkit.craftbukkit.util.CraftVector.toBlockPos(position)); } // Paper end -@@ -2454,7 +2497,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { - // Paper start - public java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { - warnUnsafeChunk("getting a faraway chunk async", x, z); // Paper -- if (Bukkit.isPrimaryThread()) { -+ if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.getHandle(), x, z)) { // Folia - region threading - net.minecraft.world.level.chunk.LevelChunk immediate = this.world.getChunkSource().getChunkAtIfLoadedImmediately(x, z); - if (immediate != null) { - return java.util.concurrent.CompletableFuture.completedFuture(new CraftChunk(immediate)); -@@ -2471,7 +2514,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { - java.util.concurrent.CompletableFuture ret = new java.util.concurrent.CompletableFuture<>(); - - ca.spottedleaf.moonrise.common.util.ChunkSystem.scheduleChunkLoad(this.getHandle(), x, z, gen, ChunkStatus.FULL, true, priority, (c) -> { -- net.minecraft.server.MinecraftServer.getServer().scheduleOnMain(() -> { -+ io.papermc.paper.threadedregions.RegionizedServer.getInstance().taskQueue.queueTickTaskQueue(this.getHandle(), x, z, () -> { // Folia - region threading - net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk)c; - if (chunk != null) this.addTicket(x, z); // Paper - ret.complete(chunk == null ? null : new CraftChunk(chunk)); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index ac11f18690434922179b61ffcc3036dea025b0cb..5bc2c3cd495b752e523510cb6c410ea4ea800732 100644 +index 5cb69d0b822e11a99a96aef4f59986d083b079f4..a2f35f6d057b098a016a40094d84c54cb5e174fd 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -75,6 +75,11 @@ public class CraftBlock implements Block { @@ -19978,7 +20442,7 @@ index ac11f18690434922179b61ffcc3036dea025b0cb..5bc2c3cd495b752e523510cb6c410ea4 + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(serverWorld, this.position, "Cannot read world asynchronously"); + } + // Folia end - region threading - this.getNMSFluid().tick(this.world.getMinecraftWorld(), this.position); + this.getNMSFluid().tick(this.world.getMinecraftWorld(), this.position, this.getNMS()); } @Override @@ -20041,10 +20505,10 @@ index a45e658996e483e9a21cfd8178153ddb7b87ae69..25303f144422469350fdc6f84320b16b List offers = waitable.get(); if (offers == null) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..88dd653f3c7871cae5983f4a0f62af0f3dd1bd99 100644 +index ddabaed899c755925ad8618b78c33dacaf2126ac..5168cf0d58013aecfd80d37fb698014f38f8e08d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -79,6 +79,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -80,6 +80,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return this.apiScheduler; }; // Paper end - Folia schedulers @@ -20056,7 +20520,7 @@ index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..88dd653f3c7871cae5983f4a0f62af0f public CraftEntity(final CraftServer server, final Entity entity) { this.server = server; -@@ -236,6 +241,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -237,6 +242,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @Override public boolean teleport(Location location, TeleportCause cause, io.papermc.paper.entity.TeleportFlag... flags) { @@ -20068,7 +20532,7 @@ index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..88dd653f3c7871cae5983f4a0f62af0f // Paper end Preconditions.checkArgument(location != null, "location cannot be null"); location.checkFinite(); -@@ -702,7 +712,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -698,7 +708,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { ImmutableSet.Builder players = ImmutableSet.builder(); ServerLevel world = ((CraftWorld) this.getWorld()).getHandle(); @@ -20077,7 +20541,7 @@ index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..88dd653f3c7871cae5983f4a0f62af0f if (entityTracker != null) { for (ServerPlayerConnection connection : entityTracker.seenBy) { -@@ -1006,7 +1016,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1002,7 +1012,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { } ServerLevel world = ((CraftWorld) this.getWorld()).getHandle(); @@ -20086,7 +20550,7 @@ index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..88dd653f3c7871cae5983f4a0f62af0f if (entityTracker == null) { return; -@@ -1025,7 +1035,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1021,7 +1031,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { } ServerLevel world = ((CraftWorld) this.getWorld()).getHandle(); @@ -20095,7 +20559,7 @@ index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..88dd653f3c7871cae5983f4a0f62af0f if (entityTracker == null) { return; -@@ -1059,29 +1069,43 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1055,29 +1065,43 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { location.checkFinite(); Location locationClone = location.clone(); // clone so we don't need to worry about mutations after this call. @@ -20104,7 +20568,7 @@ index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..88dd653f3c7871cae5983f4a0f62af0f java.util.concurrent.CompletableFuture ret = new java.util.concurrent.CompletableFuture<>(); - - world.loadChunksForMoveAsync(getHandle().getBoundingBoxAt(locationClone.getX(), locationClone.getY(), locationClone.getZ()), -- this instanceof CraftPlayer ? ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.HIGHER : ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, (list) -> { +- this instanceof CraftPlayer ? ca.spottedleaf.concurrentutil.util.Priority.HIGHER : ca.spottedleaf.concurrentutil.util.Priority.NORMAL, (list) -> { - net.minecraft.server.level.ServerChunkCache chunkProviderServer = world.getChunkSource(); - for (net.minecraft.world.level.chunk.ChunkAccess chunk : list) { - chunkProviderServer.addTicketAtLevel(net.minecraft.server.level.TicketType.POST_TELEPORT, chunk.getPos(), 33, CraftEntity.this.getEntityId()); @@ -20158,7 +20622,7 @@ index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..88dd653f3c7871cae5983f4a0f62af0f } // Paper end - more teleport API / async chunk API -@@ -1194,8 +1218,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -1190,8 +1214,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { // Paper start - tracked players API @Override public Set getTrackedPlayers() { @@ -20169,10 +20633,10 @@ index 89c8713d2c2206d1b0d8c0a392c9d13b3e736f0c..88dd653f3c7871cae5983f4a0f62af0f return java.util.Collections.emptySet(); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 42d7660efe5baa6f796f2a7606686c765b6f2478..149f442304b6af17b483822d4db1b8e760ecd556 100644 +index 7aa3ba20f63be469ec82637e79f864262e41f3c6..fecf7edb824581a7ccb90d196602b41bf22ed23f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -651,7 +651,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -656,7 +656,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void kickPlayer(String message) { @@ -20193,7 +20657,7 @@ index 42d7660efe5baa6f796f2a7606686c765b6f2478..149f442304b6af17b483822d4db1b8e7 Set relativeArguments; Set allFlags; if (flags.length == 0) { -@@ -2064,7 +2069,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2076,7 +2081,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { private void unregisterEntity(Entity other) { // Paper end ChunkMap tracker = ((ServerLevel) this.getHandle().level()).getChunkSource().chunkMap; @@ -20202,7 +20666,7 @@ index 42d7660efe5baa6f796f2a7606686c765b6f2478..149f442304b6af17b483822d4db1b8e7 if (entry != null) { entry.removePlayer(this.getHandle()); } -@@ -2161,7 +2166,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2173,7 +2178,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (original != null) otherPlayer.setUUID(original); // Paper - uuid override } @@ -20211,7 +20675,7 @@ index 42d7660efe5baa6f796f2a7606686c765b6f2478..149f442304b6af17b483822d4db1b8e7 if (entry != null && !entry.seenBy.contains(this.getHandle().connection)) { entry.updatePlayer(this.getHandle()); } -@@ -3357,7 +3362,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -3369,7 +3374,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { { if ( CraftPlayer.this.getHealth() <= 0 && CraftPlayer.this.isOnline() ) { @@ -20221,10 +20685,10 @@ index 42d7660efe5baa6f796f2a7606686c765b6f2478..149f442304b6af17b483822d4db1b8e7 } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 4632eb883e9f5efde520ee543bcad25827c0da2c..d1de8ce4b479affaa6aa493ad2c2a86d3e03deb3 100644 +index e37aaf77f94b97b736cc20ef070cefdff0400188..ebbe224d81f6a96f3b05e3379cd0c5b5ab50fcbd 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -953,7 +953,7 @@ public class CraftEventFactory { +@@ -951,7 +951,7 @@ public class CraftEventFactory { return CraftEventFactory.handleBlockSpreadEvent(world, source, target, block, 2); } @@ -20233,7 +20697,7 @@ index 4632eb883e9f5efde520ee543bcad25827c0da2c..d1de8ce4b479affaa6aa493ad2c2a86d public static boolean handleBlockSpreadEvent(LevelAccessor world, BlockPos source, BlockPos target, net.minecraft.world.level.block.state.BlockState block, int flag) { // Suppress during worldgen -@@ -965,7 +965,7 @@ public class CraftEventFactory { +@@ -963,7 +963,7 @@ public class CraftEventFactory { CraftBlockState state = CraftBlockStates.getBlockState(world, target, flag); state.setData(block); @@ -20242,7 +20706,7 @@ index 4632eb883e9f5efde520ee543bcad25827c0da2c..d1de8ce4b479affaa6aa493ad2c2a86d Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { -@@ -2225,7 +2225,7 @@ public class CraftEventFactory { +@@ -2229,7 +2229,7 @@ public class CraftEventFactory { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemStack.copyWithCount(1)); org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), CraftVector.toBukkit(to)); @@ -20252,10 +20716,10 @@ index 4632eb883e9f5efde520ee543bcad25827c0da2c..d1de8ce4b479affaa6aa493ad2c2a86d return itemStack; } diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 2f4d6b56301195f8d39ed50dffe842464065bfe1..5a24902b735cbd64dd5cd5ad46b096c4bdfa799f 100644 +index 6fef86e47e37eab6721cfd67d494afb25a2ded68..3a5d9fb6ceba1944b74bf6d5b2949a199af1b985 100644 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -521,6 +521,7 @@ public class CraftScheduler implements BukkitScheduler { +@@ -518,6 +518,7 @@ public class CraftScheduler implements BukkitScheduler { } protected CraftTask handle(final CraftTask task, final long delay) { // Paper @@ -20264,10 +20728,10 @@ index 2f4d6b56301195f8d39ed50dffe842464065bfe1..5a24902b735cbd64dd5cd5ad46b096c4 if (!this.isAsyncScheduler && !task.isSync()) { this.asyncScheduler.handle(task, delay); diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index d06aab9bd5cd901c8367f9680f5d27ddb17b3dc4..7948267b6b91100a2fd2dcb24817037c75f6953c 100644 +index 507f908916cbeb592496f963b46e4c2121a7b5e3..02de9ae7b8a3b7ef465351b02ff574cc6cacab99 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -375,6 +375,12 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -370,6 +370,12 @@ public final class CraftMagicNumbers implements UnsafeValues { throw new InvalidPluginException("Unsupported API version " + pdf.getAPIVersion()); } @@ -20281,10 +20745,10 @@ index d06aab9bd5cd901c8367f9680f5d27ddb17b3dc4..7948267b6b91100a2fd2dcb24817037c // Older than supported throw new InvalidPluginException("Plugin API version " + pdf.getAPIVersion() + " is lower than the minimum allowed version. Please update or replace it."); diff --git a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java -index bf18f9ad7dec2b09ebfcb5ec6566f2556e842f22..2dddb661b29c1c3350bfbf71a0a1b961b07ad80f 100644 +index 37458e8fd5d57acbf90a6bea4e66797cb07f69fa..7b572e0b730ba989c5df62dcef458e5ead507870 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java +++ b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java -@@ -68,6 +68,13 @@ public abstract class DelegatedGeneratorAccess implements WorldGenLevel { +@@ -66,6 +66,13 @@ public abstract class DelegatedGeneratorAccess implements WorldGenLevel { this.handle = worldAccess; } @@ -20299,10 +20763,10 @@ index bf18f9ad7dec2b09ebfcb5ec6566f2556e842f22..2dddb661b29c1c3350bfbf71a0a1b961 return this.handle; } diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index c7efdd1483b309ed8121e2203216ab288daa3117..d12f9586602769bd0c692f1cf5820b008cb4bc51 100644 +index 1d438ef44cbe4d1eedfba36d8fe5d2ad53464921..f2f5eb1a443ac411539e1c87eec60e76682b82fa 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -52,7 +52,7 @@ public class ActivationRange +@@ -51,7 +51,7 @@ public class ActivationRange RAIDER, MISC; @@ -20311,7 +20775,7 @@ index c7efdd1483b309ed8121e2203216ab288daa3117..d12f9586602769bd0c692f1cf5820b00 } // Paper start -@@ -65,26 +65,27 @@ public class ActivationRange +@@ -64,26 +64,27 @@ public class ActivationRange private static int checkInactiveWakeup(Entity entity) { Level world = entity.level(); @@ -20348,7 +20812,7 @@ index c7efdd1483b309ed8121e2203216ab288daa3117..d12f9586602769bd0c692f1cf5820b00 return config.wakeUpInactiveMonstersFor; } } -@@ -92,7 +93,7 @@ public class ActivationRange +@@ -91,7 +92,7 @@ public class ActivationRange } // Paper end @@ -20357,7 +20821,7 @@ index c7efdd1483b309ed8121e2203216ab288daa3117..d12f9586602769bd0c692f1cf5820b00 /** * Initializes an entities type on construction to specify what group this -@@ -176,10 +177,11 @@ public class ActivationRange +@@ -174,10 +175,11 @@ public class ActivationRange final int waterActivationRange = world.spigotConfig.waterActivationRange; final int flyingActivationRange = world.spigotConfig.flyingMonsterActivationRange; final int villagerActivationRange = world.spigotConfig.villagerActivationRange; @@ -20373,7 +20837,7 @@ index c7efdd1483b309ed8121e2203216ab288daa3117..d12f9586602769bd0c692f1cf5820b00 final ServerChunkCache chunkProvider = (ServerChunkCache) world.getChunkSource(); // Paper end -@@ -193,9 +195,9 @@ public class ActivationRange +@@ -191,9 +193,9 @@ public class ActivationRange // Paper end maxRange = Math.min( ( world.spigotConfig.simulationDistance << 4 ) - 8, maxRange ); @@ -20385,7 +20849,7 @@ index c7efdd1483b309ed8121e2203216ab288daa3117..d12f9586602769bd0c692f1cf5820b00 if ( world.spigotConfig.ignoreSpectatorActivation && player.isSpectator() ) { continue; -@@ -203,26 +205,33 @@ public class ActivationRange +@@ -201,26 +203,33 @@ public class ActivationRange // Paper start int worldHeight = world.getHeight(); @@ -20429,7 +20893,7 @@ index c7efdd1483b309ed8121e2203216ab288daa3117..d12f9586602769bd0c692f1cf5820b00 } // Paper end } -@@ -234,18 +243,18 @@ public class ActivationRange +@@ -231,18 +240,18 @@ public class ActivationRange * * @param chunk */ @@ -20453,7 +20917,7 @@ index c7efdd1483b309ed8121e2203216ab288daa3117..d12f9586602769bd0c692f1cf5820b00 } } } -@@ -268,10 +277,10 @@ public class ActivationRange +@@ -265,10 +274,10 @@ public class ActivationRange if (entity.getRemainingFireTicks() > 0) { return 2; } @@ -20466,7 +20930,7 @@ index c7efdd1483b309ed8121e2203216ab288daa3117..d12f9586602769bd0c692f1cf5820b00 // Paper end // quick checks. if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByFluid()) ) // Paper -@@ -394,19 +403,19 @@ public class ActivationRange +@@ -391,19 +400,19 @@ public class ActivationRange } // Paper end diff --git a/patches/server/0004-Max-pending-logins.patch b/patches/server/0004-Max-pending-logins.patch index a142d0d..ee7f365 100644 --- a/patches/server/0004-Max-pending-logins.patch +++ b/patches/server/0004-Max-pending-logins.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Max pending logins Should help the floodgates on launch diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -index 9451cccebf7acee3bd9f28f4f9d60412d1554ff4..8098b1a447a7c054e15edc09d2fa50e48f73e926 100644 +index 7fdb9304de7cf1979d57e3fac32415d7c674609d..227d62a69a453d49c28568ecb41ecef85a35405b 100644 --- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java @@ -117,7 +117,7 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener, @@ -19,7 +19,7 @@ index 9451cccebf7acee3bd9f28f4f9d60412d1554ff4..8098b1a447a7c054e15edc09d2fa50e4 // CraftBukkit start diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 45830e2f6b2f745430cb38e86678d066101656e4..98064cb4c99929ed109dac928c302c87631ad539 100644 +index c681c814046e6993a9ff6fa3545c4748452c0fb2..577f41c32bc4ebeb8a040bb86a695a10c69b3ce8 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -175,6 +175,17 @@ public abstract class PlayerList { diff --git a/patches/server/0005-Add-chunk-system-throughput-counters-to-tps.patch b/patches/server/0005-Add-chunk-system-throughput-counters-to-tps.patch index 466d3da..0a0d89d 100644 --- a/patches/server/0005-Add-chunk-system-throughput-counters-to-tps.patch +++ b/patches/server/0005-Add-chunk-system-throughput-counters-to-tps.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add chunk system throughput counters to /tps diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java -index fbdf721e8b4cfe6cef4ee60c53c680cbfc858d88..8581b8771b8cc89ff7bdb63fbfd5628a1e7d4762 100644 +index 6ab353b0d2465c3680bb3c8d0852ba0f65c00fd2..4ad647a9f98cf1c11c45f85edcba3c29e343c236 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/task/ChunkFullTask.java -@@ -28,6 +28,9 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl +@@ -30,6 +30,9 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl private final ChunkAccess fromChunk; private final PrioritisedExecutor.PrioritisedTask convertToFullTask; @@ -16,9 +16,9 @@ index fbdf721e8b4cfe6cef4ee60c53c680cbfc858d88..8581b8771b8cc89ff7bdb63fbfd5628a + public static final io.papermc.paper.util.IntervalledCounter chunkGenerates = new io.papermc.paper.util.IntervalledCounter(java.util.concurrent.TimeUnit.SECONDS.toNanos(15L)); + public ChunkFullTask(final ChunkTaskScheduler scheduler, final ServerLevel world, final int chunkX, final int chunkZ, - final NewChunkHolder chunkHolder, final ChunkAccess fromChunk, final PrioritisedExecutor.Priority priority) { + final NewChunkHolder chunkHolder, final ChunkAccess fromChunk, final Priority priority) { super(scheduler, world, chunkX, chunkZ); -@@ -41,6 +44,20 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl +@@ -43,6 +46,20 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl return ChunkStatus.FULL; } @@ -38,8 +38,8 @@ index fbdf721e8b4cfe6cef4ee60c53c680cbfc858d88..8581b8771b8cc89ff7bdb63fbfd5628a + @Override public void run() { - // See Vanilla ChunkPyramid#LOADING_PYRAMID.FULL for what this function should be doing -@@ -55,6 +72,17 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl + final PlatformHooks platformHooks = PlatformHooks.get(); +@@ -59,6 +76,17 @@ public final class ChunkFullTask extends ChunkProgressionTask implements Runnabl ((ChunkSystemPoiManager)this.world.getPoiManager()).moonrise$checkConsistency(this.fromChunk); } diff --git a/patches/server/0006-Make-CraftEntity-getHandle-and-overrides-perform-thr.patch b/patches/server/0006-Make-CraftEntity-getHandle-and-overrides-perform-thr.patch index 12fda0d..dd1f766 100644 --- a/patches/server/0006-Make-CraftEntity-getHandle-and-overrides-perform-thr.patch +++ b/patches/server/0006-Make-CraftEntity-getHandle-and-overrides-perform-thr.patch @@ -29,10 +29,10 @@ index 41bf71d116ffc5431586ce54abba7f8def6c1dcf..1cf9a7677449ab8f03fb23d835e3fadc } diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 4aefadd491f1c0c541d23fcaeaf03fd2ae995f3e..2ccc358daae43dcebf03db64526f17fbd9df23f8 100644 +index ad358909318a7e52d43e9dfb5cc7e6aa5674b9fd..451d4cf162e39acd7ed215f82a5a84f6be6e166a 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -3046,6 +3046,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3214,6 +3214,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess if (!force && (!this.canRide(entity) || !entity.canAddPassenger(this))) { return false; } else { @@ -40,7 +40,7 @@ index 4aefadd491f1c0c541d23fcaeaf03fd2ae995f3e..2ccc358daae43dcebf03db64526f17fb // CraftBukkit start if (entity.getBukkitEntity() instanceof Vehicle && this.getBukkitEntity() instanceof LivingEntity) { VehicleEnterEvent event = new VehicleEnterEvent((Vehicle) entity.getBukkitEntity(), this.getBukkitEntity()); -@@ -3067,6 +3068,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3235,6 +3236,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return false; } // CraftBukkit end @@ -48,7 +48,7 @@ index 4aefadd491f1c0c541d23fcaeaf03fd2ae995f3e..2ccc358daae43dcebf03db64526f17fb if (this.isPassenger()) { this.stopRiding(); } -@@ -3150,6 +3152,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3318,6 +3320,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); } else { // CraftBukkit start @@ -56,7 +56,7 @@ index 4aefadd491f1c0c541d23fcaeaf03fd2ae995f3e..2ccc358daae43dcebf03db64526f17fb CraftEntity craft = (CraftEntity) entity.getBukkitEntity().getVehicle(); Entity orig = craft == null ? null : craft.getHandle(); if (this.getBukkitEntity() instanceof Vehicle && entity.getBukkitEntity() instanceof LivingEntity) { -@@ -3177,6 +3180,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -3345,6 +3348,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return false; } // CraftBukkit end @@ -98,10 +98,10 @@ index 591af9d0d2fdc9953415979fc97a4a00afd85885..4a0fd1e3203342b7a5ffde579947057f } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java -index 501e2aa3a10dae94c4a8d9dfcdc902e434fcca62..865419a80712e111aeb1e436ff9c27fa4b6f37fb 100644 +index d0c30fd12aa9866900fe72b97d10c257479cf010..46d8cbe8d09cf43b489d0358498e937454d96e7b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java -@@ -130,6 +130,7 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr +@@ -133,6 +133,7 @@ public class CraftAbstractArrow extends AbstractProjectile implements AbstractAr @Override public net.minecraft.world.entity.projectile.AbstractArrow getHandle() { @@ -270,7 +270,7 @@ index ab42bc721d5b6c17c2ca6c7153b757571aea05e8..e48528689d49c01aa2b0c1599c66f3c1 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java -index 88f2a9f310f30a08893f3fa68af13a54cf72fa7f..b0cf5c7ee2542985ea704da26d36b272271ad096 100644 +index f9c113dc018702159345240d6d0de85767afa0c3..0872943dc4e5895728d12289cb23682c9bef290c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java @@ -28,8 +28,16 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud @@ -303,7 +303,7 @@ index e7f2d8de25a489d7f52c78c750e6f7f9b8fee177..75191dd32bba12b5742702a2af151b10 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java -index 9fe85d6f807e64cf02d8e1921672e3196f6d606f..8a95bc7b1250d47f518a62e625e78a7910ead7ff 100644 +index 184fe8257e5ffb0ef090ffa2833786a4db8b59ea..6c5358f77be3e46860b0c3c49d36b25286af6851 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java @@ -20,8 +20,16 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { @@ -324,7 +324,7 @@ index 9fe85d6f807e64cf02d8e1921672e3196f6d606f..8a95bc7b1250d47f518a62e625e78a79 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java -index 071be344c3265a0cd52b31ffbb02ff7a70bdf231..0152b1ba40f505bfb5ba941f6d6d0a22d825519a 100644 +index 15d50a284cafc2eb59239ca00926836526f09e06..dc455a211005f70754f3b99213b22e85821c216f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java @@ -26,6 +26,7 @@ public class CraftArrow extends CraftAbstractArrow implements Arrow { @@ -433,6 +433,27 @@ index a4c9c73691300880777483b0beb17e1bd6779d06..05951297aaed63c22f038703ad6fb68d return (net.minecraft.world.entity.monster.Blaze) this.entity; } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockAttachedEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockAttachedEntity.java +index 5b0dd9aae3fbd9257d0375a37a07c812199d64a2..d22538ecda7685093f400ee560ae53c206ed62b2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockAttachedEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockAttachedEntity.java +@@ -8,8 +8,16 @@ public class CraftBlockAttachedEntity extends CraftEntity { + super(server, entity); + } + ++ // Folia start - region threading ++ @Override ++ public BlockAttachedEntity getHandleRaw() { ++ return (BlockAttachedEntity)this.entity; ++ } ++ // Folia end - region threading ++ + @Override + public BlockAttachedEntity getHandle() { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading + return (BlockAttachedEntity) this.entity; + } + diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockDisplay.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockDisplay.java index dd91de8f24c27b9318c2a898a49991d74c100bff..b951571eda47da97ee73ba7d9b71b4f6cf0373d6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockDisplay.java @@ -455,24 +476,24 @@ index dd91de8f24c27b9318c2a898a49991d74c100bff..b951571eda47da97ee73ba7d9b71b4f6 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -index 01a9660de65688b7c1a4f9dafcb650774ce1853b..869524adfe5cb14b3cbd71a76f340bc9343b9e24 100644 +index 2a2839c31989d127739d829159a8b6e5b9a5210b..fb87800c02d5ff9bcb197170c11e305273cea083 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java -@@ -102,8 +102,16 @@ public class CraftBoat extends CraftVehicle implements Boat, io.papermc.paper.en +@@ -101,8 +101,16 @@ public abstract class CraftBoat extends CraftVehicle implements Boat, io.papermc return CraftBoat.boatStatusFromNms(this.getHandle().status); } + // Folia start - region threading + @Override -+ public net.minecraft.world.entity.vehicle.Boat getHandleRaw() { -+ return (net.minecraft.world.entity.vehicle.Boat)this.entity; ++ public AbstractBoat getHandleRaw() { ++ return (AbstractBoat)this.entity; + } + // Folia end - region threading + @Override - public net.minecraft.world.entity.vehicle.Boat getHandle() { + public AbstractBoat getHandle() { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading - return (net.minecraft.world.entity.vehicle.Boat) this.entity; + return (AbstractBoat) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java @@ -488,10 +509,10 @@ index e8e4704304504e69c7964dcd4df8ce5db9e92bf6..20630858d00fa23e911ec38788df971a } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java -index 3f3d087387d3169f352d7377c0e5a24668c3d17e..fd22213bc7a8461f5e698792c426384683fb3b7b 100644 +index 7648e2c700a55f9c0b3539dc720903238d138d54..b21f1654ddd2a4d7c85baae44fef10842905fbf9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java -@@ -11,6 +11,7 @@ public class CraftBreeze extends CraftMonster implements Breeze { +@@ -13,6 +13,7 @@ public class CraftBreeze extends CraftMonster implements Breeze { @Override public net.minecraft.world.entity.monster.breeze.Breeze getHandle() { @@ -575,24 +596,24 @@ index 4f661fbdb860cf550da0d952b775fe6f990b43b3..2dfbfbbe98815a303516d88e6ea96b9f } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java -index e4f899a6a1d055b3ea17d1114ed0228fbba53352..4d9bb569b6a957c4ebd06f93d36a0f351961fd23 100644 +index a1e04bb965f18ffd07e2f5bf827c5e4ddd6aeeda..8ba8189ddff9f35a60c31015cccf6480246cf21c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java -@@ -15,8 +15,16 @@ public class CraftChestBoat extends CraftBoat implements org.bukkit.entity.Chest +@@ -15,8 +15,16 @@ public abstract class CraftChestBoat extends CraftBoat implements org.bukkit.ent this.inventory = new CraftInventory(entity); } + // Folia start - region threading + @Override -+ public ChestBoat getHandleRaw() { -+ return (ChestBoat)this.entity; ++ public AbstractChestBoat getHandleRaw() { ++ return (AbstractChestBoat)this.entity; + } + // Folia end - region threading + @Override - public ChestBoat getHandle() { + public AbstractChestBoat getHandle() { + ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading - return (ChestBoat) this.entity; + return (AbstractChestBoat) this.entity; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftChestedHorse.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftChestedHorse.java @@ -700,6 +721,48 @@ index 7babc404e4920cd264206d4e83b1be6f841cdb8c..7a5312ab0fe3a21907a1d6b82fab9b4d return (net.minecraft.world.entity.animal.Cow) this.entity; } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreaking.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreaking.java +index 267f3c85058ef7c73e372c04493cfa6c907e44bb..df838d551fa08895e390eb793506e2f3697555f4 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreaking.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreaking.java +@@ -9,8 +9,16 @@ public class CraftCreaking extends CraftMonster implements org.bukkit.entity.Cre + super(server, entity); + } + ++ // Folia start - region threading ++ @Override ++ public Creaking getHandleRaw() { ++ return (Creaking)this.entity; ++ } ++ // Folia end - region threading ++ + @Override + public Creaking getHandle() { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading + return (Creaking) this.entity; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreakingTransient.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreakingTransient.java +index 17d55c41fa9c5f836e47e3c2a6947960411417c2..f1c6c8df621bca8c84af41cccd546f8925f4b104 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreakingTransient.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreakingTransient.java +@@ -9,8 +9,16 @@ public class CraftCreakingTransient extends CraftCreaking implements org.bukkit. + super(server, entity); + } + ++ // Folia start - region threading ++ @Override ++ public CreakingTransient getHandleRaw() { ++ return (CreakingTransient)this.entity; ++ } ++ // Folia end - region threading ++ + @Override + public CreakingTransient getHandle() { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading + return (CreakingTransient) this.entity; + } + diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreature.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreature.java index 664d9c1793b823ed03f198a936f2ebd9b7695898..6cbe6b6438296b6137ceea01b21ab6a69da2cc9c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreature.java @@ -769,10 +832,10 @@ index 48eeb1d9ba0ad6f895bfe507a6fbe4b9c9530e47..65301b94dc8d813c487deff24cd04b37 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java -index f93f8f6509b12eb9b1e07c829278bb0822dd7988..2c3c2d7f51c60a5ece610edd0bb00cba3b9d5981 100644 +index 83867b9c5497e6e793b21c482646cc419587e182..55dfb073e4355e68855580f26464af6cf1c6ac33 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java -@@ -9,8 +9,16 @@ public class CraftDolphin extends CraftWaterMob implements Dolphin { +@@ -9,8 +9,16 @@ public class CraftDolphin extends CraftAgeable implements Dolphin { super(server, entity); } @@ -979,19 +1042,10 @@ index d657fd2c507a5b215aeab0a5f3e9c2ee892a27c8..399ef60ab5f1bf02b638c8c46a72d297 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index 88dd653f3c7871cae5983f4a0f62af0f3dd1bd99..7be80f2774b5ec3d0bede096da8f2b6d1cf7b09b 100644 +index 5168cf0d58013aecfd80d37fb698014f38f8e08d..982778c4828e79bc7a55745418beb04f9c56cc78 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -@@ -498,7 +498,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { - - @Override - public UUID getUniqueId() { -- return this.getHandle().getUUID(); -+ return this.getHandleRaw().getUUID(); // Folia - region threading - } - - @Override -@@ -513,6 +513,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { +@@ -514,6 +514,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { } public Entity getHandle() { @@ -1189,7 +1243,7 @@ index 8117faa0c89a966d057f4bf251c03a09d1e8797e..7c3827e6ef608ff15be9bced4788b09f } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFox.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFox.java -index c455deb4fd2a7684bcc01a8212c362a2375c190b..5f0ddb932df148859dc6a699082934cac8d48fcf 100644 +index bb2b59ce9775a0d1dd9828885e57c14cf40d9f04..90dcbf746c5effa98c09059552674a3e428ac1b9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFox.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFox.java @@ -14,8 +14,16 @@ public class CraftFox extends CraftAnimals implements Fox { @@ -1441,7 +1495,7 @@ index 9b6ff0f64966c78a3233860bb0840182b52f01bc..fb34651a9e4ed0cb05721d15524a26f8 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 7dcfb45c24d7743956be514c7d554e06aac77b3e..6a052ed8d66a62b42c98a3b1d60263dd8018fed1 100644 +index e345cdbfab44a0f5da80d738798dbb4424b7ab5c..2a4ed66335e4fd88aefabb063ec04fe803bc728e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -298,8 +298,16 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @@ -1677,10 +1731,10 @@ index e9f471e60af0725ec34e2985d63ae9ea9f88590a..cd824fc65ac2b1fe55710da4700f7c31 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 57b71a3894638253c6d24d4967a96768834bb02b..a82e2be0d104fefbf9a213256b82b3354fd1c098 100644 +index d0c409f4efad289e3e325f44b500fc72589d89d4..828d371cda28d68246c721a44331bd3f145db3a5 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -478,6 +478,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -487,6 +487,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { this.getHandle().invulnerableTime = ticks; } @@ -1694,7 +1748,7 @@ index 57b71a3894638253c6d24d4967a96768834bb02b..a82e2be0d104fefbf9a213256b82b335 @Override public int getNoActionTicks() { return this.getHandle().getNoActionTime(); -@@ -491,6 +498,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -500,6 +507,7 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { @Override public net.minecraft.world.entity.LivingEntity getHandle() { @@ -1787,10 +1841,10 @@ index e6782a48d22ba1e683e3fe463e970e8a5ed60fbd..afaa4570c1991cd4260ffcdba823ba24 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -index 8920af5a0dfe737c1f38d906b53e6a278456d2aa..5652ec4aea839fae3f8ea31d7cd5c80ecf129fb5 100644 +index b42bce0c4f4b3aac2729cfdad392d863245ed693..d3ffa2b4402fdd005104d07d92e4066c6170615e 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java -@@ -86,8 +86,16 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart { +@@ -77,8 +77,16 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart { } // Paper end @@ -1850,7 +1904,7 @@ index 451f3a6f0b47493da3af3f5d6baced6a8c97f350..d4f98fe5eb5e463679ebc5b82b077c98 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java -index 1b41026ab638bb2764b19429706eb0aded5aad12..4d242bed3bd40c9749236e138f81d5e8583f7dc3 100644 +index 1be1f6d23f2224d4d8720d40f2e530736b1bae81..eee08d53714b485bffd1398506ed0cb3b7002d2c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java @@ -11,8 +11,16 @@ public class CraftMinecartFurnace extends CraftMinecart implements PoweredMineca @@ -1892,11 +1946,32 @@ index 3a3563a1bdbc0d84d973b3a04b50b78b4bc3d379..1e86ce7c1a3fc1f4eae2d8136fc0d879 return (net.minecraft.world.entity.vehicle.MinecartHopper) super.getHandle(); } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java +index e8ece01669373ecf6552d33b2ed72668524e2650..fbb5c2e2a136cd03eb1f4b4b5ef289d6a6c39173 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java +@@ -162,8 +162,16 @@ final class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMine + this.getHandle().getSpawner().spawnRange = spawnRange; + } + ++ // Folia start - region threading ++ @Override ++ public MinecartSpawner getHandleRaw() { ++ return (MinecartSpawner)this.entity; ++ } ++ // Folia end - region threading ++ + @Override + public MinecartSpawner getHandle() { ++ ca.spottedleaf.moonrise.common.util.TickThread.ensureTickThread(this.entity, "Accessing entity state off owning region's thread"); // Folia - region threading + return (MinecartSpawner) this.entity; + } + diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java -index 79b608e89d4d1f76a58868c585bb87c82e2689b1..7884de5348f325ee12db41a521a042be4b33a793 100644 +index 1fe06d3958295acc8211b7837b172262beb87f92..a35f88cf511c7d0231b1d973250b90b72eaec78c 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java -@@ -42,8 +42,16 @@ public final class CraftMinecartTNT extends CraftMinecart implements ExplosiveMi +@@ -62,8 +62,16 @@ public final class CraftMinecartTNT extends CraftMinecart implements ExplosiveMi this.getHandle().explode(power); } @@ -1914,7 +1989,7 @@ index 79b608e89d4d1f76a58868c585bb87c82e2689b1..7884de5348f325ee12db41a521a042be } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java -index 5f9f7e325e3e0276f7a475c4a4725cc0e1b54afd..b6721b3388a5c921e9e621798329f17434683a87 100644 +index 778a9d3f8bfe5dba59e1e655e4eeb8822678b8cf..b4ec6c1f8ea5d5c34f2ecb2b066e49993ae79dc7 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java @@ -54,8 +54,16 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob, io.pape @@ -1965,7 +2040,7 @@ index 706c74c832f6893df3797023f68add31139c7d57..1cf155fc23f13691f86673eac3084d75 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java -index 5c5b64bd058684520fa175bfd10622ff57856b7c..8acaa5f8153d643e2558110bb7be512514a27532 100644 +index 596146ad7899c21645df8834ce5f0afd6c1b0604..78f6e16a745924419d5aad53f95d767d87bdf5d0 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java @@ -19,6 +19,13 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow, io.paperm @@ -2024,7 +2099,7 @@ index ecdac2cf74e99f0d69e053dece11ab891973dc2b..fa365c38c9e0f671df1481c8b36bc993 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java -index 98a4463c9f194f33f4f85d95a0b9fa061cf6faaf..50c1259a16db9f7f134ea6aeb43f29dc100214d3 100644 +index b1b139b773b37e6ec2afea85c500387d6ba9800e..38c1eb97de420cd7dea6a9f76ef644ecdf8c30b8 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java @@ -50,8 +50,16 @@ public class CraftPainting extends CraftHanging implements Painting { @@ -2234,10 +2309,10 @@ index 2638c341bc02f201f7ab17fdebcdbdf3a7ec05bf..074b2919be2b5544b0a46e6cd32f6c57 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 149f442304b6af17b483822d4db1b8e760ecd556..12a2da086f249b3dbd61e5749b9856a2fce9ac7b 100644 +index fecf7edb824581a7ccb90d196602b41bf22ed23f..b2ae1de0b18a7b5c684b04e3f81fdf071e013c61 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -669,7 +669,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -674,7 +674,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void kick(net.kyori.adventure.text.Component message, org.bukkit.event.player.PlayerKickEvent.Cause cause) { @@ -2246,7 +2321,7 @@ index 149f442304b6af17b483822d4db1b8e760ecd556..12a2da086f249b3dbd61e5749b9856a2 final ServerGamePacketListenerImpl connection = this.getHandle().connection; if (connection != null) { connection.disconnect(message == null ? net.kyori.adventure.text.Component.empty() : message, cause); -@@ -2315,9 +2315,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2327,9 +2327,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this; } @@ -2392,10 +2467,10 @@ index 09796ce15658e3f7c223a265a547a51ee729ed40..bfca2951d18f7451787877b5a6503b05 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSalmon.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSalmon.java -index d4d8ce60098c74508e2de9541bf6534988779764..bf4b61e56345b1f2ee83d8aceaf66c199590c258 100644 +index 7660cc21e936002ebb23510f0ec2b58d71e5157d..a13976b2712413ef9fdeecd1e3ca762238d4efd9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSalmon.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSalmon.java -@@ -9,8 +9,16 @@ public class CraftSalmon extends io.papermc.paper.entity.PaperSchoolableFish imp +@@ -10,8 +10,16 @@ public class CraftSalmon extends io.papermc.paper.entity.PaperSchoolableFish imp super(server, entity); } @@ -2728,10 +2803,10 @@ index b4afc37c21fc478df44fca7ec3fbc33d337dc6b7..bf3236f673118539d7cfb883bcdf84de } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSquid.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSquid.java -index a6e3b61c391a8b266d2b030d9ba600ac6be76952..abc26a620552659fbcfbcbb90a3fd203f995c46f 100644 +index 067a95ea50418601acfb8b9453d1291161bb706a..3a41ef5fdecee262f3e8899deec360c35ddf1b6f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSquid.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSquid.java -@@ -9,8 +9,16 @@ public class CraftSquid extends CraftWaterMob implements Squid { +@@ -9,8 +9,16 @@ public class CraftSquid extends CraftAgeable implements Squid { super(server, entity); } @@ -2770,7 +2845,7 @@ index 9472a6f9c9584048abf1f8d11ab6254b7c7a287d..de8f656818192f35cca228724db3d17e } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTNTPrimed.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTNTPrimed.java -index dac3d34677688ac560bc1be2087a08479ef71b87..ec4ae01daa16139b4d2d42c3771eb51d00f55c0a 100644 +index a61aec087fa7cec27a803668bdc1b9e6eb336755..1c3826dc868a78402531b6abdddd017c83dae853 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTNTPrimed.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTNTPrimed.java @@ -42,8 +42,16 @@ public class CraftTNTPrimed extends CraftEntity implements TNTPrimed { @@ -3023,10 +3098,10 @@ index e9ec3455eabc473e104b5342a615a38c1ac25a4f..3a65ae7e6ac1894855e4eafecc9c2bb8 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -index bd2987fa1fb194a581567134ed980e8fc043f435..46c4a33c4cb82049aa60fc7fc47707dcbd8c733e 100644 +index 8e895d6f84f7d84b219f2424909dd42e5f08dec4..e2341684f56a14b3a05fa65d9ac7b3adb52d9077 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java -@@ -33,8 +33,16 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { +@@ -34,8 +34,16 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { super(server, entity); } @@ -3224,7 +3299,7 @@ index bc978391255c9414e06ff393f2e6707d329d020a..8d436a1453c8a66422c2a73576427317 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java -index 86574da257731de7646a712ed73384955fe35aa3..94b699c156884c28c017b528d07f21c041b4ceb1 100644 +index ecd33b4add46acbe4e4f8879c0601220423d66ca..5b4c42eb9ade06ad2470e938a8717637e658e026 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java @@ -31,8 +31,16 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf { @@ -3266,7 +3341,7 @@ index c134c4bb8c0377ceb7f8a5c40c94fd6312a9e448..d334e4a3ea075670e0aa7ea1429ffe42 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java -index 46336111dcf62a29390e724b1879c84c697076e9..dbb43c825724c3f13171e8991d53e7d40899670d 100644 +index dfc2b40e20069705f92d86a6898e3e8348bf4dcd..9e158d32dc13f8890511de1496d9d5b4c1956e3b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java @@ -12,8 +12,16 @@ public class CraftZombie extends CraftMonster implements Zombie { diff --git a/patches/server/0007-Throw-UnsupportedOperationException-for-broken-APIs.patch b/patches/server/0007-Throw-UnsupportedOperationException-for-broken-APIs.patch index 0f19cc5..696fdae 100644 --- a/patches/server/0007-Throw-UnsupportedOperationException-for-broken-APIs.patch +++ b/patches/server/0007-Throw-UnsupportedOperationException-for-broken-APIs.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Throw UnsupportedOperationException() for broken APIs diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f9b399214848098149eb1f3a4043028d242dd454..dee23b4b96b7f2c6af54a6affe385b183479f8cc 100644 +index 7cc63a4a9759d3926f843cfedbc79986d1ece926..a8975cee866cf2c617b6d4976df71e5c20cf0e3d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1312,6 +1312,7 @@ public final class CraftServer implements Server { +@@ -1320,6 +1320,7 @@ public final class CraftServer implements Server { @Override public World createWorld(WorldCreator creator) { @@ -16,7 +16,7 @@ index f9b399214848098149eb1f3a4043028d242dd454..dee23b4b96b7f2c6af54a6affe385b18 Preconditions.checkState(this.console.getAllLevels().iterator().hasNext(), "Cannot create additional worlds on STARTUP"); //Preconditions.checkState(!this.console.isIteratingOverLevels, "Cannot create a world while worlds are being ticked"); // Paper - Cat - Temp disable. We'll see how this goes. Preconditions.checkArgument(creator != null, "WorldCreator cannot be null"); -@@ -1490,6 +1491,7 @@ public final class CraftServer implements Server { +@@ -1498,6 +1499,7 @@ public final class CraftServer implements Server { @Override public boolean unloadWorld(World world, boolean save) { @@ -53,7 +53,7 @@ index 253574890a9ed23d38a84680ba1eb221dc72b310..ce8b91f00f925960ad17f381162a1129 this.board.setDisplayObjective(CraftScoreboardTranslations.fromBukkitSlot(slot), null); } diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -index b3e1adeb932da9b3bed16acd94e2f16da48a7c72..46a8262f21ef95714c122240ee86f01858010047 100644 +index f3184be3853dfc4df4ae4b8af764dfef07628ef4..99ba4d19b72a66ea1fc83fda16d37aaa0f154abb 100644 --- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java +++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java @@ -42,6 +42,7 @@ public final class CraftScoreboardManager implements ScoreboardManager { diff --git a/patches/server/0010-Prevent-block-updates-in-non-loaded-or-non-owned-chu.patch b/patches/server/0010-Prevent-block-updates-in-non-loaded-or-non-owned-chu.patch index f3bbeb7..1979e6d 100644 --- a/patches/server/0010-Prevent-block-updates-in-non-loaded-or-non-owned-chu.patch +++ b/patches/server/0010-Prevent-block-updates-in-non-loaded-or-non-owned-chu.patch @@ -9,10 +9,10 @@ add explicit block update suppression techniques, it's better than the server crashing. diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index d518487433088f090edb0d12e222b85f0c93b792..db232ac0cc27ddff4bc25ba9b9a5f3a1996fc4e8 100644 +index 35b18a9ecce6c7b743badbf384f40b48f2fc73be..54bafb8f67361525484c5c58ee8e6568c0801477 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1936,7 +1936,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1966,7 +1966,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl Direction enumdirection = (Direction) iterator.next(); BlockPos blockposition1 = pos.relative(enumdirection); @@ -22,23 +22,23 @@ index d518487433088f090edb0d12e222b85f0c93b792..db232ac0cc27ddff4bc25ba9b9a5f3a1 if (iblockdata.is(Blocks.COMPARATOR)) { diff --git a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java -index 9d69e439ff853465303c2abd896e6c5314752e1e..69e1748d9d40a8cbf672ba49a8a01e9ff847efd9 100644 +index fa1c4defd0d4e4cd888eb26eed131539d0ed573f..afd09a54ee3962943cdf4150a41817fdb0da6615 100644 --- a/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DetectorRailBlock.java -@@ -134,9 +134,9 @@ public class DetectorRailBlock extends BaseRailBlock { +@@ -135,9 +135,9 @@ public class DetectorRailBlock extends BaseRailBlock { while (iterator.hasNext()) { BlockPos blockposition1 = (BlockPos) iterator.next(); - BlockState iblockdata1 = world.getBlockState(blockposition1); + BlockState iblockdata1 = !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((ServerLevel)world, blockposition1) ? null : world.getBlockStateIfLoaded(blockposition1); // Folia - block updates in unloaded chunks -- world.neighborChanged(iblockdata1, blockposition1, iblockdata1.getBlock(), pos, false); -+ if (iblockdata1 != null) world.neighborChanged(iblockdata1, blockposition1, iblockdata1.getBlock(), pos, false); // Folia - block updates in unloaded chunks +- world.neighborChanged(iblockdata1, blockposition1, iblockdata1.getBlock(), (Orientation) null, false); ++ if (iblockdata1 != null) world.neighborChanged(iblockdata1, blockposition1, iblockdata1.getBlock(), (Orientation) null, false); // Folia - block updates in unloaded chunks } } diff --git a/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java b/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java -index 9603d8c84ff483030dc08e82d3579b89e5c1f6e9..e2d1f25010d4ec8051c8635440b6c9bfa1e6ae88 100644 +index b763361a8f0f1b46093d5dd9afe8dba0cadf9c78..78c6fc0755b149515a98163cb7c68589595c365c 100644 --- a/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java +++ b/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java @@ -104,9 +104,9 @@ public class PoweredRailBlock extends BaseRailBlock { @@ -54,60 +54,59 @@ index 9603d8c84ff483030dc08e82d3579b89e5c1f6e9..e2d1f25010d4ec8051c8635440b6c9bf } else { RailShape blockpropertytrackposition1 = (RailShape) iblockdata.getValue(PoweredRailBlock.SHAPE); diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java -index c4471342eea4f9e2b0916fc1c5f1b24bc07757fd..25b4764358f0a20418d268625609d05c4aa01037 100644 +index 0020e7bb7b19179a898cd8835d12cfa37eccdcc2..cf3307a3e30c08e741e25ef5757d6597089f6919 100644 --- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java +++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java -@@ -199,8 +199,9 @@ public class RedStoneWireBlock extends Block { - while (iterator.hasNext()) { - Direction enumdirection = (Direction) iterator.next(); - RedstoneSide blockpropertyredstoneside = (RedstoneSide) state.getValue((Property) RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(enumdirection)); -+ BlockState currState; blockposition_mutableblockposition.setWithOffset(pos, enumdirection); // Folia - block updates in unloaded chunks - -- if (blockpropertyredstoneside != RedstoneSide.NONE && !world.getBlockState(blockposition_mutableblockposition.setWithOffset(pos, enumdirection)).is((Block) this)) { -+ if (blockpropertyredstoneside != RedstoneSide.NONE && (currState = (world instanceof net.minecraft.server.level.ServerLevel serverLevel && !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(serverLevel, pos) ? null : world.getBlockStateIfLoaded(blockposition_mutableblockposition))) != null && !currState.is((Block) this)) { // Folia - block updates in unloaded chunks - blockposition_mutableblockposition.move(Direction.DOWN); - BlockState iblockdata1 = world.getBlockState(blockposition_mutableblockposition); +@@ -237,7 +237,8 @@ public class RedStoneWireBlock extends Block { + for (Direction direction : Direction.Plane.HORIZONTAL) { + RedstoneSide redstoneSide = state.getValue(PROPERTY_BY_DIRECTION.get(direction)); +- if (redstoneSide != RedstoneSide.NONE && !world.getBlockState(mutableBlockPos.setWithOffset(pos, direction)).is(this)) { ++ BlockState currState; mutableBlockPos.setWithOffset(pos, direction); // Folia - block updates in unloaded chunks ++ if (redstoneSide != RedstoneSide.NONE && (currState = (world instanceof net.minecraft.server.level.ServerLevel serverLevel && !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(serverLevel, pos) ? null : world.getBlockStateIfLoaded(mutableBlockPos.setWithOffset(pos, direction)))) != null && !currState.is(this)) { // Folia - block updates in unloaded chunks + mutableBlockPos.move(Direction.DOWN); + BlockState blockState = world.getBlockState(mutableBlockPos); + if (blockState.is(this)) { diff --git a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java -index 2c9640001dba727981ad336eefade6d438eeb0ac..67bd721c4f9b22e07f9ab75ca019b4c9e9080a4c 100644 +index 63b12dcb1b86e15607ebbaa157d7a330c089862d..d1d8360f1ae931b22e1712b498ae66b7649be90d 100644 --- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java +++ b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java -@@ -119,7 +119,8 @@ public class CollectingNeighborUpdater implements NeighborUpdater { - @Override +@@ -124,7 +124,8 @@ public class CollectingNeighborUpdater implements NeighborUpdater { public boolean runNext(Level world) { - BlockPos blockPos = this.sourcePos.relative(NeighborUpdater.UPDATE_ORDER[this.idx++]); + Direction direction = NeighborUpdater.UPDATE_ORDER[this.idx++]; + BlockPos blockPos = this.sourcePos.relative(direction); - BlockState blockState = world.getBlockState(blockPos); + BlockState blockState = !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)world, blockPos) ? null : world.getBlockStateIfLoaded(blockPos); // Folia - block updates in unloaded chunks + if (blockState != null) { // Folia - block updates in unloaded chunks - // Paper start - Call BlockPhysicsEvent - try { - org.bukkit.event.block.BlockPhysicsEvent event = new org.bukkit.event.block.BlockPhysicsEvent( -@@ -134,6 +135,7 @@ public class CollectingNeighborUpdater implements NeighborUpdater { - world.lastPhysicsProblem = blockPos; + Orientation orientation = null; + if (world.enabledFeatures().contains(FeatureFlags.REDSTONE_EXPERIMENTS)) { + if (this.orientation == null) { +@@ -137,6 +138,7 @@ public class CollectingNeighborUpdater implements NeighborUpdater { } - // Paper end - Call BlockPhysicsEvent + + NeighborUpdater.executeUpdate(world, blockState, blockPos, this.sourceBlock, orientation, false, this.sourcePos); // Paper - Add source block to BlockPhysicsEvent + } // Folia - block updates in unloaded chunks if (this.idx < NeighborUpdater.UPDATE_ORDER.length && NeighborUpdater.UPDATE_ORDER[this.idx] == this.skipDirection) { this.idx++; } -@@ -150,7 +152,9 @@ public class CollectingNeighborUpdater implements NeighborUpdater { +@@ -153,7 +155,9 @@ public class CollectingNeighborUpdater implements NeighborUpdater { implements CollectingNeighborUpdater.NeighborUpdates { @Override public boolean runNext(Level world) { + if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)world, this.pos) && world.getChunkIfLoaded(this.pos) != null) { // Folia - block updates in unloaded chunks - NeighborUpdater.executeShapeUpdate(world, this.direction, this.state, this.pos, this.neighborPos, this.updateFlags, this.updateLimit); + NeighborUpdater.executeShapeUpdate(world, this.direction, this.pos, this.neighborPos, this.neighborState, this.updateFlags, this.updateLimit); + } // Folia - block updates in unloaded chunks return false; } } -@@ -158,8 +162,8 @@ public class CollectingNeighborUpdater implements NeighborUpdater { - static record SimpleNeighborUpdate(BlockPos pos, Block block, BlockPos neighborPos) implements CollectingNeighborUpdater.NeighborUpdates { +@@ -161,8 +165,8 @@ public class CollectingNeighborUpdater implements NeighborUpdater { + static record SimpleNeighborUpdate(BlockPos pos, Block block, @Nullable Orientation orientation) implements CollectingNeighborUpdater.NeighborUpdates { @Override public boolean runNext(Level world) { - BlockState blockState = world.getBlockState(this.pos); -- NeighborUpdater.executeUpdate(world, blockState, this.pos, this.block, this.neighborPos, false); +- NeighborUpdater.executeUpdate(world, blockState, this.pos, this.block, this.orientation, false); + BlockState blockState = !ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor((net.minecraft.server.level.ServerLevel)world, this.pos) ? null : world.getBlockStateIfLoaded(this.pos); // Folia - block updates in unloaded chunks -+ if (blockState != null) NeighborUpdater.executeUpdate(world, blockState, this.pos, this.block, this.neighborPos, false); // Folia - block updates in unloaded chunks ++ if (blockState != null) NeighborUpdater.executeUpdate(world, blockState, this.pos, this.block, this.orientation, false); // Folia - block updates in unloaded chunks return false; } } diff --git a/patches/server/0011-Block-reading-in-world-tile-entities-on-worldgen-thr.patch b/patches/server/0011-Block-reading-in-world-tile-entities-on-worldgen-thr.patch index acda785..b35dfc8 100644 --- a/patches/server/0011-Block-reading-in-world-tile-entities-on-worldgen-thr.patch +++ b/patches/server/0011-Block-reading-in-world-tile-entities-on-worldgen-thr.patch @@ -7,10 +7,10 @@ The returned TE may be in the world, in which case it is unsafe for the current thread to modify or access its contents. diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -index d7d332d8ba3442887e80d2c3d7bddb9de2674c2d..f135ed136aa01bf18b4bd107109db8f8ebf440d2 100644 +index 1eb8022f3e31603322e6c56516304afc9a11bbec..87ddae289972b8e0dd0b48a07e23c627b598bae3 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java -@@ -92,6 +92,11 @@ public class ImposterProtoChunk extends ProtoChunk implements ca.spottedleaf.moo +@@ -91,6 +91,11 @@ public class ImposterProtoChunk extends ProtoChunk implements ca.spottedleaf.moo @Nullable @Override public BlockEntity getBlockEntity(BlockPos pos) { diff --git a/patches/server/0012-Skip-worldstate-access-when-waking-players-up-during.patch b/patches/server/0012-Skip-worldstate-access-when-waking-players-up-during.patch index dd1ac8a..4991074 100644 --- a/patches/server/0012-Skip-worldstate-access-when-waking-players-up-during.patch +++ b/patches/server/0012-Skip-worldstate-access-when-waking-players-up-during.patch @@ -9,10 +9,10 @@ data deserialization and is racey even in Vanilla. But in Folia, some accesses may throw and as such we need to fix this directly. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 00b3c3c60f67d129058a888b7bd5e7fb031063da..e4a68f43c1a48fe8193623c646eb40bc5f664c76 100644 +index f2884eefe00a35e19c83e069f65490dff95144a8..19eb204e5d3cd6ef8f2a31fae32e75dbf07ffb96 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -709,7 +709,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +@@ -799,7 +799,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple this.getBukkitEntity().readExtraData(nbt); // CraftBukkit if (this.isSleeping()) { @@ -22,10 +22,10 @@ index 00b3c3c60f67d129058a888b7bd5e7fb031063da..e4a68f43c1a48fe8193623c646eb40bc // CraftBukkit start diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 551ad6757e76ec9c731488f0355d4950ad1b0bd4..9b8fd458c851d72901568845d973330ed58260a9 100644 +index 77eab187d4d6e22e5f8722029107c5613a9a7300..b63393c131f736cd51666c675ac18918e038eca6 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -4451,6 +4451,11 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -4605,6 +4605,11 @@ public abstract class LivingEntity extends Entity implements Attackable { } }); diff --git a/patches/server/0015-Fix-off-region-raid-heroes.patch b/patches/server/0015-Fix-off-region-raid-heroes.patch index 5a54f02..3009674 100644 --- a/patches/server/0015-Fix-off-region-raid-heroes.patch +++ b/patches/server/0015-Fix-off-region-raid-heroes.patch @@ -9,10 +9,10 @@ raid before it's completion, it would throw an exception due to not being on the same region thread anymore. diff --git a/src/main/java/net/minecraft/world/entity/raid/Raid.java b/src/main/java/net/minecraft/world/entity/raid/Raid.java -index e1987d1d6e5fd05e155c05dd1fdaf569e303d74a..909d1966b2f22c65ef4b887521b3b0e772f2a7ee 100644 +index 5ff4a4af7f166f5f977efe41263ca487fe1b270b..1df579db8286113f8412fe678259fb53098e57ed 100644 --- a/src/main/java/net/minecraft/world/entity/raid/Raid.java +++ b/src/main/java/net/minecraft/world/entity/raid/Raid.java -@@ -429,14 +429,22 @@ public class Raid { +@@ -423,14 +423,22 @@ public class Raid { LivingEntity entityliving = (LivingEntity) entity; if (!entity.isSpectator()) { diff --git a/patches/server/0016-Sync-vehicle-position-to-player-position-on-player-d.patch b/patches/server/0016-Sync-vehicle-position-to-player-position-on-player-d.patch index 485d2ec..e07e7a7 100644 --- a/patches/server/0016-Sync-vehicle-position-to-player-position-on-player-d.patch +++ b/patches/server/0016-Sync-vehicle-position-to-player-position-on-player-d.patch @@ -6,21 +6,21 @@ Subject: [PATCH] Sync vehicle position to player position on player data load This allows the player to be re-positioned before logging into the world without causing thread checks to trip on Folia. -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 98064cb4c99929ed109dac928c302c87631ad539..20eeae6e968ecb5d67f16d0d2f56632e038a89b4 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -516,7 +516,13 @@ public abstract class PlayerList { - if (optional.isPresent() && ((CompoundTag) optional.get()).contains("RootVehicle", 10)) { - CompoundTag nbttagcompound = ((CompoundTag) optional.get()).getCompound("RootVehicle"); - ServerLevel finalWorldServer = worldserver1; // CraftBukkit - decompile error -+ Vec3 playerPos = player.position(); // Paper - force sync root vehicle to player position - Entity entity = EntityType.loadEntityRecursive(nbttagcompound.getCompound("Entity"), worldserver1, (entity1) -> { -+ // Paper start - force sync root vehicle to player position -+ if (entity1.distanceToSqr(player) > (5.0 * 5.0)) { -+ entity1.setPosRaw(playerPos.x, playerPos.y, playerPos.z, true); -+ } -+ // Paper end - force sync root vehicle to player position - return !finalWorldServer.addWithUUID(entity1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity1; // CraftBukkit - decompile error // Paper - Entity#getEntitySpawnReason - }); +diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java +index 19eb204e5d3cd6ef8f2a31fae32e75dbf07ffb96..68a88928a3aae9d2ea6cd18088ede0a54c31d0d2 100644 +--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java ++++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +@@ -925,7 +925,13 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple + if (world instanceof ServerLevel) { + ServerLevel worldserver = (ServerLevel) world; + CompoundTag nbttagcompound = ((CompoundTag) nbt.get()).getCompound("RootVehicle"); ++ Vec3 playerPos = this.position(); // Paper - force sync root vehicle to player position + Entity entity = EntityType.loadEntityRecursive(nbttagcompound.getCompound("Entity"), worldserver, EntitySpawnReason.LOAD, (entity1) -> { ++ // Paper start - force sync root vehicle to player position ++ if (entity1.distanceToSqr(ServerPlayer.this) > (5.0 * 5.0)) { ++ entity1.setPosRaw(playerPos.x, playerPos.y, playerPos.z, true); ++ } ++ // Paper end - force sync root vehicle to player position + return !worldserver.addWithUUID(entity1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity1; // CraftBukkit - decompile error // Paper - Entity#getEntitySpawnReason + }); diff --git a/patches/server/0017-Region-profiler.patch b/patches/server/0017-Region-profiler.patch index a15ce66..2adeb9d 100644 --- a/patches/server/0017-Region-profiler.patch +++ b/patches/server/0017-Region-profiler.patch @@ -190,7 +190,7 @@ index 0000000000000000000000000000000000000000..19c13bd372711bce978a463f85130f1e +} diff --git a/src/main/java/ca/spottedleaf/leafprofiler/LProfilerRegistry.java b/src/main/java/ca/spottedleaf/leafprofiler/LProfilerRegistry.java new file mode 100644 -index 0000000000000000000000000000000000000000..1d4f1bdb12d0f1371b62a484b535afd7dcbe1cd7 +index 0000000000000000000000000000000000000000..cf81748afe993e486ce27ae65e0148071b029423 --- /dev/null +++ b/src/main/java/ca/spottedleaf/leafprofiler/LProfilerRegistry.java @@ -0,0 +1,118 @@ @@ -301,11 +301,11 @@ index 0000000000000000000000000000000000000000..1d4f1bdb12d0f1371b62a484b535afd7 + public static final int MISC_MOB_SPAWN_TICK = GLOBAL_REGISTRY.createType(ProfileType.TIMER, "Misc Mob Spawn Tick"); + public static final int BROADCAST_BLOCK_CHANGES = GLOBAL_REGISTRY.createType(ProfileType.TIMER, "Broadcast Block Changes"); + public static final int ENTITY_TRACKER_TICK = GLOBAL_REGISTRY.createType(ProfileType.TIMER, "Entity Tracker Tick"); -+ public static final int TRACKED_UNLOADED_ENTITY_COUNTS = GLOBAL_REGISTRY.createType(ProfileType.COUNTER, "Total Untracked Unloaded Entities"); + public static final int TRACKED_ENTITY_COUNTS = GLOBAL_REGISTRY.createType(ProfileType.COUNTER, "Total Tracked Entities"); + public static final int POI_MANAGER_TICK = GLOBAL_REGISTRY.createType(ProfileType.TIMER, "POI Manager Tick"); + public static final int PROCESS_UNLOADS = GLOBAL_REGISTRY.createType(ProfileType.TIMER, "Process Unloads"); + public static final int BLOCK_EVENT_TICK = GLOBAL_REGISTRY.createType(ProfileType.TIMER, "Block Event Tick"); ++ public static final int ACTIVATE_ENTITIES = GLOBAL_REGISTRY.createType(ProfileType.TIMER, "Activate Entities"); + public static final int ENTITY_TICK = GLOBAL_REGISTRY.createType(ProfileType.TIMER, "Entity Tick"); + public static final int DRAGON_FIGHT_TICK = GLOBAL_REGISTRY.createType(ProfileType.TIMER, "Dragon Fight Tick"); + public static final int TILE_ENTITY = GLOBAL_REGISTRY.createType(ProfileType.TIMER, "Tile Entities"); @@ -927,10 +927,10 @@ index 0000000000000000000000000000000000000000..95c0e6416afafbb633f0a30ae22df166 + ) {} +} diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -index 4b36209f016b025087da359ab49e44bd677cd937..707d4aa8a56f2fc33456f3441c4daf973a27ef2d 100644 +index 3a476713964002734a9e67fd9b6dfa497b590657..e176d2d2387e171ff163853131dcf8d1af9a268d 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkHolderManager.java -@@ -1442,7 +1442,9 @@ public final class ChunkHolderManager { +@@ -1459,7 +1459,9 @@ public final class ChunkHolderManager { } public boolean processTicketUpdates() { @@ -941,10 +941,10 @@ index 4b36209f016b025087da359ab49e44bd677cd937..707d4aa8a56f2fc33456f3441c4daf97 private static final ThreadLocal> CURRENT_TICKET_UPDATE_SCHEDULING = new ThreadLocal<>(); diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java -index 3210d4cb97301d6fa5ffe76fd7c263ab7aa0a8be..60399be0046dbb06be643461c8f3ce1491542dfd 100644 +index 9e7e10fe46dbbd03d690a65af6ae719d1665bc6a..6edbe46c5c2eb74bca7e437474a6e992f45a04f8 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/NewChunkHolder.java -@@ -1672,6 +1672,8 @@ public final class NewChunkHolder { +@@ -1680,6 +1680,8 @@ public final class NewChunkHolder { public SaveStat save(final boolean shutdown) { TickThread.ensureTickThread(this.world, this.chunkX, this.chunkZ, "Cannot save data off-main"); @@ -953,14 +953,14 @@ index 3210d4cb97301d6fa5ffe76fd7c263ab7aa0a8be..60399be0046dbb06be643461c8f3ce14 ChunkAccess chunk = this.getCurrentChunk(); PoiChunk poi = this.getPoiChunk(); -@@ -1718,6 +1720,7 @@ public final class NewChunkHolder { - } - - return executedUnloadTask | canSaveChunk | canSaveEntities | canSavePOI ? new SaveStat(executedUnloadTask || canSaveChunk, canSaveEntities, canSavePOI): null; +@@ -1738,6 +1740,7 @@ public final class NewChunkHolder { + canSavePOI | executedUnloadTasks[MoonriseRegionFileIO.RegionFileType.POI_DATA.ordinal()] + ) + : null; + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_SAVE); } // Folia - profiler } - static final class AsyncChunkSerializeTask implements Runnable { + private boolean saveChunk(final ChunkAccess chunk, final boolean unloading) { diff --git a/src/main/java/io/papermc/paper/command/PaperCommands.java b/src/main/java/io/papermc/paper/command/PaperCommands.java index a587d83b78af4efc484f939529acf70834f60d7e..45f76aaaa7dedb77a83b4a2c87905bf9a099a93c 100644 --- a/src/main/java/io/papermc/paper/command/PaperCommands.java @@ -1360,13 +1360,13 @@ index 0000000000000000000000000000000000000000..e36fd244f71a92d11c6ee45944948be5 + } +} diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -index fbc619a132c6ca6b1abab51ac230be29367e9c6e..97817400b70b2579f3a8750f7f33197a5db7ba94 100644 +index d6eb8f495688a1b65a4c419aa3ee655cd8eb322a..f338b273613840ed366ab13b528373e7091631e8 100644 --- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java +++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -@@ -53,7 +53,10 @@ public class PacketUtils { +@@ -52,7 +52,10 @@ public class PacketUtils { + if (listener instanceof ServerCommonPacketListenerImpl serverCommonPacketListener && serverCommonPacketListener.processedDisconnect) return; // CraftBukkit - Don't handle sync packets for kicked players if (listener.shouldHandleMessage(packet)) { - co.aikar.timings.Timing timing = co.aikar.timings.MinecraftTimings.getPacketTiming(packet); // Paper - timings - try (co.aikar.timings.Timing ignored = timing.startTiming()) { // Paper - timings + try { + final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler + final int packetTimerId = profiler.getOrCreateTimerAndStart(() -> "Packet Handler: ".concat(io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(packet.getClass().getName()))); try { // Folia - profiler packet.handle(listener); @@ -1375,100 +1375,109 @@ index fbc619a132c6ca6b1abab51ac230be29367e9c6e..97817400b70b2579f3a8750f7f33197a if (exception instanceof ReportedException) { ReportedException reportedexception = (ReportedException) exception; diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 84f1f7956065de039837ceeaeee30259a7df4118..4ed79a51c89d54a7b2ab65a99b5b09cc807f4d4e 100644 +index ee55c53d40dbf51f47627a6b56060e32fd215353..b261d166eb09386275ba52372cca56fceaac002b 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1654,6 +1654,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() % autosavePeriod == 0; // Folia - region threading -+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.AUTOSAVE); try { // Folia - profiler ++ foliaProfiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.AUTOSAVE); try { // Folia - profiler try { this.isSaving = true; if (playerSaveInterval > 0) { -@@ -1734,6 +1745,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Folia - region threading - entityplayer.connection.suspendFlushing(); -@@ -1875,7 +1888,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop trackerEntities = worldData.trackerEntities; // Folia - region threading @@ -1502,157 +1510,134 @@ index 6f746f5ce9751dce4912f7633c126788eb684bd0..74524dcd4539a31e9d0037cd607ffbfc final Entity entity = trackerEntitiesRaw[i]; final ChunkMap.TrackedEntity tracker = ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerEntity)entity).moonrise$getTrackedEntity(); if (tracker == null) { -@@ -928,6 +938,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -964,6 +974,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + tracker.serverEntity.sendChanges(); } - ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerTrackedEntity)tracker).moonrise$clearPlayers(); } + profiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.TRACKED_ENTITY_COUNTS, (long)totalEntities); // Folia - profiler -+ profiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.TRACKED_UNLOADED_ENTITY_COUNTS, (long)unloadedEntitiesRaw.length); // Folia - profiler + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_TRACKER_TICK); } // Folia - profiler } // Paper end - optimise entity tracker diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index b0e41b79d357f7e1b189985b4752accc78f05bbb..f7311d6efc2119b9dbe062a439850a890c9bf6b8 100644 +index f58dadcf5f3822fd18a0d1dfb775b3d7cd7abde9..220db29a8901fbbfbec2b95be994f0ea0144b98d 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -397,19 +397,26 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon +@@ -455,18 +455,25 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @Override public void tick(BooleanSupplier shouldKeepTicking, boolean tickChunks) { -+ final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler - this.level.getProfiler().push("purge"); - this.level.timings.doChunkMap.startTiming(); // Spigot -+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_HOLDER_MANAGER_TICK); try { // Folia - profiler ++ final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler + ProfilerFiller gameprofilerfiller = Profiler.get(); + + gameprofilerfiller.push("purge"); ++ foliaProfiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_HOLDER_MANAGER_TICK); try { // Folia - profiler if (this.level.tickRateManager().runsNormally() || !tickChunks || this.level.spigotConfig.unloadFrozenChunks) { // Spigot this.distanceManager.purgeStaleTickets(); } this.runDistanceManagerUpdates(); -+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_HOLDER_MANAGER_TICK); } // Folia - profiler - this.level.timings.doChunkMap.stopTiming(); // Spigot - this.level.getProfiler().popPush("chunks"); ++ } finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_HOLDER_MANAGER_TICK); } // Folia - profiler + gameprofilerfiller.popPush("chunks"); if (tickChunks) { - this.level.timings.chunks.startTiming(); // Paper - timings -+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.PLAYER_CHUNK_LOADER_TICK); try { // Folia - profiler ++ foliaProfiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.PLAYER_CHUNK_LOADER_TICK); try { // Folia - profiler ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getPlayerChunkLoader().tick(); // Paper - rewrite chunk system -+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.PLAYER_CHUNK_LOADER_TICK); } // Folia - profiler -+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_TICK); try { // Folia - profiler ++ } finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.PLAYER_CHUNK_LOADER_TICK); } // Folia - profiler ++ foliaProfiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_TICK); try { // Folia - profiler this.tickChunks(); -+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_TICK); } // Folia - profiler - this.level.timings.chunks.stopTiming(); // Paper - timings ++ } finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_TICK); } // Folia - profiler this.chunkMap.tick(); } -@@ -424,6 +431,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + +@@ -478,6 +485,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon private void tickChunks() { io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.level.getCurrentWorldData(); // Folia - region threading -+ final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler - long chunksTicked = 0; // Paper - rewrite chunk system ++ final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler //long i = this.level.getGameTime(); // Folia - region threading long j = 1L; // Folia - region threading -@@ -436,6 +444,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - gameprofilerfiller.push("filteringLoadedChunks"); - // Paper start - chunk tick iteration optimisations - List list; -+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_TICK_COLLECT_CHUNKS); try { // Folia - profiler - { - final ca.spottedleaf.moonrise.common.list.ReferenceList tickingChunks = - ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel) this.level).moonrise$getTickingChunks(); -@@ -452,6 +461,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - regionizedWorldData.iterationCopy, size // Folia - region threading - ); - } -+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_TICK_COLLECT_CHUNKS); } // Folia - profiler - // Paper end - chunk tick iteration optimisations - Iterator iterator = null; // Paper - chunk tick iteration optimisations - if (this.level.getServer().tickRateManager().runsNormally()) this.level.timings.chunkTicks.startTiming(); // Paper -@@ -465,6 +475,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - // Paper start - Optional per player mob spawns - int naturalSpawnChunkCount = k; - NaturalSpawner.SpawnState spawnercreature_d; // moved down -+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.MOB_SPAWN_ENTITY_COUNT); try { // Folia - profiler - if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled - // re-set mob counts - for (ServerPlayer player : this.level.getLocalPlayers()) { // Folia - region threading -@@ -484,6 +495,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - } else { - spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); // Folia - region threading - note: function only cares about loaded entities, doesn't need all - } -+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.MOB_SPAWN_ENTITY_COUNT); } // Folia - profiler - // Paper end - Optional per player mob spawns - this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings -@@ -505,6 +517,9 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit - Iterator iterator1 = list.iterator(); +@@ -491,7 +499,9 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon -+ long spawnChunkCount = 0L; // Folia - profiler -+ long randomChunkCount = 0L; // Folia - profiler -+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.SPAWN_AND_RANDOM_TICK); try { // Folia - profiler - while (iterator1.hasNext()) { - ServerChunkCache.ChunkAndHolder chunkproviderserver_a = (ServerChunkCache.ChunkAndHolder) iterator1.next(); - LevelChunk chunk1 = chunkproviderserver_a.chunk; -@@ -513,10 +528,12 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - if (true && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair)) { // Paper - rewrite chunk system - chunk1.incrementInhabitedTime(j); - if (flag && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkcoordintpair, true)) { // Spigot -+ ++spawnChunkCount; // Folia - profiler - NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1); - } - - if (true) { // Paper - rewrite chunk system -+ ++randomChunkCount; // Folia - profiler - this.level.tickChunk(chunk1, l); - // Paper start - rewrite chunk system - if ((++chunksTicked & 7L) == 0L) { -@@ -526,19 +543,25 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - } - } - } -+ profiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.SPAWN_CHUNK_COUNT, spawnChunkCount); // Folia - profiler -+ profiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.RANDOM_CHUNK_TICK_COUNT, randomChunkCount); // Folia - profiler -+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.SPAWN_AND_RANDOM_TICK); } // Folia - profiler - this.level.timings.chunkTicks.stopTiming(); // Paper - - gameprofilerfiller.popPush("customSpawners"); - if (flag) { -+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.MISC_MOB_SPAWN_TICK); try { // Folia - profiler - try (co.aikar.timings.Timing ignored = this.level.timings.miscMobSpawning.startTiming()) { // Paper - timings - this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); - } // Paper - timings -+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.MISC_MOB_SPAWN_TICK); } // Folia - profiler + try { + gameprofilerfiller.push("filteringTickingChunks"); ++ foliaProfiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_TICK_COLLECT_CHUNKS); try { // Folia - profiler + this.collectTickingChunks(list); ++ } finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_TICK_COLLECT_CHUNKS); } // Folia - profiler + gameprofilerfiller.popPush("shuffleChunks"); + // Paper start - chunk tick iteration optimisation + this.shuffleRandom.setSeed(this.level.random.nextLong()); +@@ -504,7 +514,9 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon } } - gameprofilerfiller.popPush("broadcast"); - // Paper start - chunk tick iteration optimisations - this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing -+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.BROADCAST_BLOCK_CHANGES); try { // Folia - profiler - { - final it.unimi.dsi.fastutil.objects.ObjectArrayList chunks = (it.unimi.dsi.fastutil.objects.ObjectArrayList)list; - final ServerChunkCache.ChunkAndHolder[] raw = chunks.elements(); -@@ -552,6 +575,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon - holder.holder().broadcastChanges(holder.chunk()); - } - } -+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.BROADCAST_BLOCK_CHANGES); } // Folia - profiler - this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing - // Paper end - chunk tick iteration optimisations ++ foliaProfiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.BROADCAST_BLOCK_CHANGES); try { // Folia - profiler + this.broadcastChangedChunks(gameprofilerfiller); ++ } finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.BROADCAST_BLOCK_CHANGES); } // Folia - profiler gameprofilerfiller.pop(); + } + } +@@ -552,11 +564,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + + private void tickChunks(ProfilerFiller profiler, long timeDelta, List chunks) { + io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.level.getCurrentWorldData(); // Folia - region threading ++ final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler + profiler.popPush("naturalSpawnCount"); + int j = this.distanceManager.getNaturalSpawnChunkCount(); + // Paper start - Optional per player mob spawns + final int naturalSpawnChunkCount = j; + NaturalSpawner.SpawnState spawnercreature_d; // moved down ++ foliaProfiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.MOB_SPAWN_ENTITY_COUNT); try { // Folia - profiler + if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled + // re-set mob counts + for (ServerPlayer player : this.level.getLocalPlayers()) { // Folia - region threading +@@ -576,6 +590,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + } else { + spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, regionizedWorldData.getLoadedEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); // Folia - region threading - note: function only cares about loaded entities, doesn't need all + } ++ } finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.MOB_SPAWN_ENTITY_COUNT); } // Folia - profiler + // Paper end - Optional per player mob spawns + + regionizedWorldData.lastSpawnState = spawnercreature_d; // Folia - region threading +@@ -603,6 +618,9 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + + Iterator iterator = chunks.iterator(); + ++ long spawnChunkCount = 0L; // Folia - profiler ++ long randomChunkCount = 0L; // Folia - profiler ++ foliaProfiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.SPAWN_AND_RANDOM_TICK); try { // Folia - profiler + while (iterator.hasNext()) { + LevelChunk chunk = (LevelChunk) iterator.next(); + ChunkPos chunkcoordintpair = chunk.getPos(); +@@ -616,10 +634,15 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon + this.level.tickChunk(chunk, k); + } + } ++ foliaProfiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.SPAWN_CHUNK_COUNT, spawnChunkCount); // Folia - profiler ++ foliaProfiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.RANDOM_CHUNK_TICK_COUNT, randomChunkCount); // Folia - profiler ++ } finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.SPAWN_AND_RANDOM_TICK); } // Folia - profiler + + profiler.popPush("customSpawners"); + if (flag) { ++ foliaProfiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.MISC_MOB_SPAWN_TICK); try { // Folia - profiler + this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); ++ } finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.MISC_MOB_SPAWN_TICK); } // Folia - profiler + } + + } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index f03f968d1526fbcff1ae87376370ba5976c2b807..90d78ddf8518c0df307cdaa8b7cfb5549491c6e5 100644 +index f8d865c7127e7a05bb8ce34b86bc41eed8b9de23..2d721d9f4bf6e4e7c9168b5f1605edb98bbb2fc8 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -709,6 +709,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -725,6 +725,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public void tick(BooleanSupplier shouldKeepTicking, io.papermc.paper.threadedregions.TickRegions.TickRegionData region) { // Folia - regionised ticking final io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.getCurrentWorldData(); // Folia - regionised ticking + final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler - ProfilerFiller gameprofilerfiller = this.getProfiler(); + ProfilerFiller gameprofilerfiller = Profiler.get(); regionizedWorldData.setHandlingTick(true); // Folia - regionised ticking -@@ -737,9 +738,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -753,22 +754,32 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe if (!this.isDebug() && flag) { j = regionizedWorldData.getRedstoneGameTime(); // Folia - region threading gameprofilerfiller.push("blockTicks"); @@ -1665,60 +1650,53 @@ index f03f968d1526fbcff1ae87376370ba5976c2b807..90d78ddf8518c0df307cdaa8b7cfb554 + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.FLUID_TICK); } // Folia - profiler gameprofilerfiller.pop(); } - this.timings.scheduledBlocks.stopTiming(); // Paper -@@ -747,18 +752,24 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + gameprofilerfiller.popPush("raid"); if (flag) { - this.timings.raids.startTiming(); // Paper - timings + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.RAIDS_TICK); try { // Folia - profiler this.raids.tick(); + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.RAIDS_TICK); } // Folia - profiler - this.timings.raids.stopTiming(); // Paper - timings } gameprofilerfiller.popPush("chunkSource"); - this.timings.chunkProviderTick.startTiming(); // Paper - timings + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_PROVIDER_TICK); try { // Folia - profiler this.getChunkSource().tick(shouldKeepTicking, true); + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CHUNK_PROVIDER_TICK); } // Folia - profiler - this.timings.chunkProviderTick.stopTiming(); // Paper - timings gameprofilerfiller.popPush("blockEvents"); if (flag) { - this.timings.doSounds.startTiming(); // Spigot + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.BLOCK_EVENT_TICK); try { // Folia - profiler this.runBlockEvents(); + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.BLOCK_EVENT_TICK); } // Folia - profiler - this.timings.doSounds.stopTiming(); // Spigot } -@@ -774,6 +785,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + regionizedWorldData.setHandlingTick(false); // Folia - regionised ticking +@@ -782,6 +793,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + if (flag1 || this.emptyTime++ < 300) { gameprofilerfiller.push("entities"); - this.timings.tickEntities.startTiming(); // Spigot if (this.dragonFight != null && flag) { + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.DRAGON_FIGHT_TICK); try { // Folia - profiler if (ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this, this.dragonFight.origin)) { // Folia - region threading gameprofilerfiller.push("dragonFight"); this.dragonFight.tick(); -@@ -786,10 +798,12 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -794,9 +806,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe fightCenter ); } // Folia end - region threading + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.DRAGON_FIGHT_TICK); } // Folia - profiler } ++ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ACTIVATE_ENTITIES); try { // Folia - profiler org.spigotmc.ActivationRange.activateEntities(this); // Spigot - this.timings.entityTick.startTiming(); // Spigot ++ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ACTIVATE_ENTITIES); } // Folia - profiler + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_TICK); try { // Folia - profiler regionizedWorldData.forEachTickingEntity((entity) -> { // Folia - regionised ticking if (!entity.isRemoved()) { - if (false && this.shouldDiscardEntity(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed -@@ -817,10 +831,13 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. + if (!tickratemanager.isEntityFrozen(entity)) { +@@ -822,8 +838,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } } }); + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_TICK); } // Folia - profiler - this.timings.entityTick.stopTiming(); // Spigot - this.timings.tickEntities.stopTiming(); // Spigot gameprofilerfiller.pop(); + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.TILE_ENTITY); try { // Folia - profiler this.tickBlockEntities(); @@ -1726,7 +1704,7 @@ index f03f968d1526fbcff1ae87376370ba5976c2b807..90d78ddf8518c0df307cdaa8b7cfb554 } gameprofilerfiller.push("entityManagement"); -@@ -880,12 +897,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. +@@ -885,12 +904,15 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe } public void tickCustomSpawners(boolean spawnMonsters, boolean spawnAnimals) { @@ -1742,78 +1720,79 @@ index f03f968d1526fbcff1ae87376370ba5976c2b807..90d78ddf8518c0df307cdaa8b7cfb554 } } -@@ -1352,6 +1372,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - // Paper start- timings - final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); - timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper -+ // Folia start - timer +@@ -1345,6 +1367,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + }); + gameprofilerfiller.incrementCounter("tickNonPassenger"); + final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); // Paper - EAR 2 ++ // Folia start - profiler + final int timerId = isActive ? entity.getType().tickTimerId : entity.getType().inactiveTickTimerId; + final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); + profiler.startTimer(timerId); -+ // Folia end - timer - try { - // Paper end - timings - entity.setOldPosAndRot(); -@@ -1377,7 +1402,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. ++ try { ++ // Folia end - profiler + if (isActive) { // Paper - EAR 2 + entity.tick(); + // Folia start - region threading +@@ -1359,6 +1387,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // Folia end - region threading } else { entity.inactiveTick(); } // Paper - EAR 2 - this.getProfiler().pop(); -- } finally { timer.stopTiming(); } // Paper - timings -+ } finally { timer.stopTiming(); profiler.stopTimer(timerId); } // Paper - timings // Folia - timer + gameprofilerfiller.pop(); ++ } finally { profiler.stopTimer(timerId); } // Folia - timer Iterator iterator = entity.getPassengers().iterator(); while (iterator.hasNext()) { -@@ -1401,6 +1426,11 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - // Paper - EAR 2 - final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); - co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper -+ // Folia start - timer +@@ -1377,6 +1406,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + private void tickPassenger(Entity vehicle, Entity passenger, boolean isActive) { // Paper - EAR 2 + if (!passenger.isRemoved() && passenger.getVehicle() == vehicle) { + if (passenger instanceof Player || this.getCurrentWorldData().hasEntityTickingEntity(passenger)) { // Folia - region threading ++ // Folia start - profiler + final int timerId = isActive ? passenger.getType().tickTimerId : passenger.getType().inactiveTickTimerId; + final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); + profiler.startTimer(timerId); -+ // Folia end - timer - try { - // Paper end ++ try { ++ // Folia end - profiler passenger.setOldPosAndRot(); -@@ -1440,7 +1470,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. - this.tickPassenger(passenger, entity2); + ++passenger.tickCount; + ProfilerFiller gameprofilerfiller = Profiler.get(); +@@ -1414,6 +1449,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + this.tickPassenger(passenger, entity2, isActive); // Paper - EAR 2 } -- } finally { timer.stopTiming(); }// Paper - EAR2 timings -+ } finally { timer.stopTiming(); profiler.stopTimer(timerId); }// Paper - EAR2 timings // Folia - timer ++ } finally { profiler.stopTimer(timerId); } // Folia - profiler } } else { passenger.stopRiding(); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 20eeae6e968ecb5d67f16d0d2f56632e038a89b4..9acb477df682a27b4340e4068d6b81df1925fc0b 100644 +index 577f41c32bc4ebeb8a040bb86a695a10c69b3ce8..12ae1c610f59f13416753e237fd0d7073bcd372b 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -1299,6 +1299,7 @@ public abstract class PlayerList { +@@ -1258,6 +1258,7 @@ public abstract class PlayerList { public void saveAll(int interval) { io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main + final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler - MinecraftTimings.savePlayers.startTiming(); // Paper int numSaved = 0; long now = System.nanoTime(); // Folia - region threading -@@ -1310,7 +1311,9 @@ public abstract class PlayerList { + long timeInterval = (long)interval * io.papermc.paper.threadedregions.TickRegionScheduler.TIME_BETWEEN_TICKS; // Folia - region threading +@@ -1268,7 +1269,9 @@ public abstract class PlayerList { } // Folia end - region threading - if (interval == -1 || now - entityplayer.lastSave >= timeInterval) { // Folia - region threading + if (interval == -1 || now - player.lastSave >= timeInterval) { // Folia - region threading + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.PLAYER_SAVE); try { // Folia - profiler - this.save(entityplayer); + this.save(player); + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.PLAYER_SAVE); } // Folia - profiler - // Folia start - region threading - if (interval != -1 && max != -1 && ++numSaved >= max) { - break; + if (interval != -1 && ++numSaved >= io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick()) { break; } + } + // Paper end - Incremental chunk and player saving diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index cb61462d4691a055a4b25f7b953609d8a154fdfe..c74a01a8551457507441d266b6923b4248560abf 100644 +index c8c2394558952d7ca57d29874485251b8f2b3400..0d18403c6c25555f78e2d6810520839f30258c8e 100644 --- a/src/main/java/net/minecraft/world/entity/EntityType.java +++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -338,6 +338,13 @@ public class EntityType implements FeatureElement, EntityTypeT +@@ -412,7 +412,20 @@ public class EntityType implements FeatureElement, EntityTypeT return BuiltInRegistries.ENTITY_TYPE.getOptional(ResourceLocation.tryParse(id)); } +- public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet canSpawnInside, EntityDimensions dimensions, float spawnBoxScale, int maxTrackDistance, int trackTickInterval, String translationKey, Optional> lootTable, FeatureFlagSet requiredFeatures) { + // Folia start - profiler + public final int tickTimerId; + public final int inactiveTickTimerId; @@ -1821,14 +1800,8 @@ index cb61462d4691a055a4b25f7b953609d8a154fdfe..c74a01a8551457507441d266b6923b42 + public final int passengerInactiveTickTimerId; + // Folia end - profiler + - public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet canSpawnInside, EntityDimensions dimensions, float spawnBoxScale, int maxTrackDistance, int trackTickInterval, FeatureFlagSet requiredFeatures) { - // Paper start - this(factory, spawnGroup, saveable, summonable, fireImmune, spawnableFarFromPlayer, canSpawnInside, dimensions, spawnBoxScale, maxTrackDistance, trackTickInterval, requiredFeatures, "custom"); -@@ -348,6 +355,12 @@ public class EntityType implements FeatureElement, EntityTypeT - this.passengerTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerTick"); - this.passengerInactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerInactiveTick"); - // Paper end -+ // Folia start - profiler ++ // Folia start - profiler ++ public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet canSpawnInside, EntityDimensions dimensions, float spawnBoxScale, int maxTrackDistance, int trackTickInterval, String translationKey, Optional> lootTable, FeatureFlagSet requiredFeatures, String id) { + this.tickTimerId = ca.spottedleaf.leafprofiler.LProfilerRegistry.GLOBAL_REGISTRY.getOrCreateTimer("Entity Tick: " + id); + this.inactiveTickTimerId = ca.spottedleaf.leafprofiler.LProfilerRegistry.GLOBAL_REGISTRY.getOrCreateTimer("Inactive Entity Tick: " + id); + this.passengerTickTimerId = ca.spottedleaf.leafprofiler.LProfilerRegistry.GLOBAL_REGISTRY.getOrCreateTimer("Passenger Entity Tick: " + id); @@ -1837,11 +1810,20 @@ index cb61462d4691a055a4b25f7b953609d8a154fdfe..c74a01a8551457507441d266b6923b42 this.builtInRegistryHolder = BuiltInRegistries.ENTITY_TYPE.createIntrusiveHolder(this); this.factory = factory; this.category = spawnGroup; +@@ -963,7 +976,7 @@ public class EntityType implements FeatureElement, EntityTypeT + Util.fetchChoiceType(References.ENTITY_TREE, registryKey.location().toString()); + } + +- return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions.withAttachments(this.attachments), this.spawnDimensionsScale, this.clientTrackingRange, this.updateInterval, (String) this.descriptionId.get(registryKey), (Optional) this.lootTable.get(registryKey), this.requiredFeatures); ++ return new EntityType<>(this.factory, this.category, this.serialize, this.summon, this.fireImmune, this.canSpawnFarFromPlayer, this.immuneTo, this.dimensions.withAttachments(this.attachments), this.spawnDimensionsScale, this.clientTrackingRange, this.updateInterval, (String) this.descriptionId.get(registryKey), (Optional) this.lootTable.get(registryKey), this.requiredFeatures, registryKey.toString()); // Folia - profiler + } + } + diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index db232ac0cc27ddff4bc25ba9b9a5f3a1996fc4e8..3e739362046d624dd46412f7c50a7220d26593cf 100644 +index 54bafb8f67361525484c5c58ee8e6568c0801477..3d96f7ae648b47cc7494578d9776e7ea6dee0964 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -203,6 +203,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -204,6 +204,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl public final ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup moonrise$getEntityLookup() { return this.entityLookup; } @@ -1850,104 +1832,84 @@ index db232ac0cc27ddff4bc25ba9b9a5f3a1996fc4e8..3e739362046d624dd46412f7c50a7220 + // Folia end - profiler @Override - public void moonrise$setEntityLookup(final ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup entityLookup) { -@@ -787,6 +790,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl - this.maxSection = ca.spottedleaf.moonrise.common.util.WorldUtil.getMaxSection(this); - // Paper end - optimise collisions + public final void moonrise$setEntityLookup(final ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup entityLookup) { +@@ -936,6 +939,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + this.tileLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.tileMaxTickTime); this.chunkPacketBlockController = this.paperConfig().anticheat.antiXray.enabled ? new com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray(this, executor) : com.destroystokyo.paper.antixray.ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray + this.entityLookup = new ca.spottedleaf.moonrise.patches.chunk_system.level.entity.dfl.DefaultEntityLookup(this); // Paper - rewrite chunk system + // Folia start - profiler -+ this.tickTimerId = ca.spottedleaf.leafprofiler.LProfilerRegistry.GLOBAL_REGISTRY.getOrCreateTimer(" Tick World: " + resourcekey.location().toString()); ++ this.tickTimerId = ca.spottedleaf.leafprofiler.LProfilerRegistry.GLOBAL_REGISTRY.getOrCreateTimer("Tick World: " + resourcekey.location().toString()); + // Folia end - profiler } // Paper start - Cancel hit for vanished players -@@ -1406,17 +1412,21 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1480,14 +1486,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } protected void tickBlockEntities() { + final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler - ProfilerFiller gameprofilerfiller = this.getProfiler(); + ProfilerFiller gameprofilerfiller = Profiler.get(); gameprofilerfiller.push("blockEntities"); - this.timings.tileEntityPending.startTiming(); // Spigot final io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = this.getCurrentWorldData(); // Folia - regionised ticking regionizedWorldData.seTtickingBlockEntities(true); // Folia - regionised ticking + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.TILE_ENTITY_PENDING); try { // Folia - profiler regionizedWorldData.pushPendingTickingBlockEntities(); // Folia - regionised ticking + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.TILE_ENTITY_PENDING); } // Folia - profiler List blockEntityTickers = regionizedWorldData.getBlockEntityTickers(); // Folia - regionised ticking - this.timings.tileEntityPending.stopTiming(); // Spigot - this.timings.tileEntityTick.startTiming(); // Spigot + profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.TILE_ENTITY_TICK); try { // Folia - profiler // Spigot start // Iterator iterator = this.blockEntityTickers.iterator(); boolean flag = this.tickRateManager().runsNormally(); -@@ -1445,6 +1455,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +@@ -1516,6 +1526,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl } } blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 // Folia - regionised ticking + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.TILE_ENTITY_TICK); } // Folia - profiler - this.timings.tileEntityTick.stopTiming(); // Spigot regionizedWorldData.seTtickingBlockEntities(false); // Folia - regionised ticking + gameprofilerfiller.pop(); diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntityType.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntityType.java -index 96b99aab3720e5bdf293fd4a95944c7218ce43c0..e7691f856f85469c06f2b5a2a3db3120ec6f193d 100644 +index dea945a9b278353647dca3ed001158c198dab668..422c9aeb761092496089a1b2e1dd9c5fe8f5b2bc 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntityType.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntityType.java -@@ -283,10 +283,17 @@ public class BlockEntityType { +@@ -245,10 +245,14 @@ public class BlockEntityType { } - Type type = Util.fetchChoiceType(References.BLOCK_ENTITY, id); -- return Registry.register(BuiltInRegistries.BLOCK_ENTITY_TYPE, id, builder.build(type)); -+ return Registry.register(BuiltInRegistries.BLOCK_ENTITY_TYPE, id, builder.build(type, id)); // Folia - profiler + Util.fetchChoiceType(References.BLOCK_ENTITY, id); +- return Registry.register(BuiltInRegistries.BLOCK_ENTITY_TYPE, id, new BlockEntityType<>(blockEntitySupplier, Set.of(blocks))); ++ return Registry.register(BuiltInRegistries.BLOCK_ENTITY_TYPE, id, new BlockEntityType<>(blockEntitySupplier, Set.of(blocks), id)); // Folia - profiler } - public BlockEntityType(BlockEntityType.BlockEntitySupplier factory, Set blocks, Type type) { -+ // Folia start - profiler -+ this(factory, blocks, type, "custom"); -+ } +- private BlockEntityType(BlockEntityType.BlockEntitySupplier factory, Set blocks) { ++ // Folia start - profiler + public final int tileEntityTimingId; -+ public BlockEntityType(BlockEntityType.BlockEntitySupplier factory, Set blocks, Type type, String id) { ++ private BlockEntityType(BlockEntityType.BlockEntitySupplier factory, Set blocks, String id) { + this.tileEntityTimingId = ca.spottedleaf.leafprofiler.LProfilerRegistry.GLOBAL_REGISTRY.getOrCreateTimer("Tile Entity Tick: " + id); + // Folia end - profiler this.factory = factory; this.validBlocks = blocks; - this.dataType = type; -@@ -331,7 +338,12 @@ public class BlockEntityType { - } - - public BlockEntityType build(Type type) { -- return new BlockEntityType<>(this.factory, this.validBlocks, type); -+ // Folia start - profiler -+ return this.build(type, "custom"); -+ } -+ public BlockEntityType build(Type type, String id) { -+ return new BlockEntityType<>(this.factory, this.validBlocks, type, id); -+ // Folia end - profiler - } } - } diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 27e68ed3a508f16f53422c5aa1631b804c8eff9e..ea95a382561dcf2bb958a08351d493087a49336a 100644 +index 877f68f9abfc659f489d6571efc1b431e1240ed6..4bccb94cf953ebd4dfd4f1620ad1784ef235356f 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -1044,11 +1044,14 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -1074,10 +1074,13 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p BlockPos blockposition = this.blockEntity.getBlockPos(); if (LevelChunk.this.isTicking(blockposition)) { + final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle profiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler + final int timerId = this.blockEntity.getType().tileEntityTimingId; // Folia - profiler try { - ProfilerFiller gameprofilerfiller = LevelChunk.this.level.getProfiler(); + ProfilerFiller gameprofilerfiller = Profiler.get(); gameprofilerfiller.push(this::getType); - this.blockEntity.tickTimer.startTiming(); // Spigot + profiler.startTimer(timerId); try { // Folia - profiler BlockState iblockdata = LevelChunk.this.getBlockState(blockposition); if (this.blockEntity.getType().isValid(iblockdata)) { -@@ -1063,6 +1066,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p +@@ -1092,6 +1095,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p } // Paper end - Remove the Block Entity if it's invalid } @@ -1956,10 +1918,10 @@ index 27e68ed3a508f16f53422c5aa1631b804c8eff9e..ea95a382561dcf2bb958a08351d49308 gameprofilerfiller.pop(); } catch (Throwable throwable) { diff --git a/src/main/java/net/minecraft/world/ticks/LevelTicks.java b/src/main/java/net/minecraft/world/ticks/LevelTicks.java -index ea161048b68de3c8cdcba5f4cb66eb1531364b2e..073d8176a7ee347f81edb18292de26629ca95e06 100644 +index 3fc6b4f93885fe447ed068bc5e0784daad655696..7d3067a7df48171f6c8cda12d5da6d721c085a60 100644 --- a/src/main/java/net/minecraft/world/ticks/LevelTicks.java +++ b/src/main/java/net/minecraft/world/ticks/LevelTicks.java -@@ -250,6 +250,12 @@ public class LevelTicks implements LevelTickAccess { +@@ -248,6 +248,12 @@ public class LevelTicks implements LevelTickAccess { } private void runCollectedTicks(BiConsumer ticker) { diff --git a/patches/server/0018-Disable-spark-profiler.patch b/patches/server/0018-Disable-spark-profiler.patch index bc8978e..8c23536 100644 --- a/patches/server/0018-Disable-spark-profiler.patch +++ b/patches/server/0018-Disable-spark-profiler.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Disable spark profiler It's not thread-safe. The plugin instead needs to be used. diff --git a/src/main/java/io/papermc/paper/SparksFly.java b/src/main/java/io/papermc/paper/SparksFly.java -index 19c4aa20617f555d02f9c1c5a93b7204ab7251d8..4b30b05dcd99176715d49133fb99b96383a0ecbc 100644 +index 2ad5b9b0b7e18780ee73310451d9fa73f44c4bdb..b332645ed65928100f580221d8a9948bc77e362e 100644 --- a/src/main/java/io/papermc/paper/SparksFly.java +++ b/src/main/java/io/papermc/paper/SparksFly.java -@@ -109,7 +109,7 @@ public final class SparksFly { +@@ -116,7 +116,7 @@ public final class SparksFly { private void enable() { if (!this.enabled) { @@ -18,7 +18,7 @@ index 19c4aa20617f555d02f9c1c5a93b7204ab7251d8..4b30b05dcd99176715d49133fb99b963 this.enabled = true; this.spark.enable(); } else { -@@ -161,7 +161,7 @@ public final class SparksFly { +@@ -168,7 +168,7 @@ public final class SparksFly { } public static boolean isPluginPreferred() { diff --git a/update.txt b/update.txt deleted file mode 100644 index e69de29..0000000