From ff1e30907cfcda86ba790ee2800abc09c4c23ae5 Mon Sep 17 00:00:00 2001 From: MoePus <547007249@qq.com> Date: Sun, 18 Jan 2026 23:20:49 +0900 Subject: [PATCH] 1.0.1 --- gradle.properties | 2 +- icon.png | Bin 0 -> 16279 bytes .../moepus/serverwarashi/ChunkLoadInfo.java | 56 ++++++++++++++++++ .../com/moepus/serverwarashi/TicketOwner.java | 17 ++++++ .../moepus/serverwarashi/WarashiCommands.java | 49 +++++++++++++-- .../mixin/EntitySectionStorageAccessor.java | 12 ++++ ...ersistentEntitySectionManagerAccessor.java | 12 ++++ .../mixin/ServerLevelAcessor.java | 13 ++++ src/main/resources/serverwarashi.mixins.json | 3 + 9 files changed, 157 insertions(+), 7 deletions(-) create mode 100644 icon.png create mode 100644 src/main/java/com/moepus/serverwarashi/ChunkLoadInfo.java create mode 100644 src/main/java/com/moepus/serverwarashi/mixin/EntitySectionStorageAccessor.java create mode 100644 src/main/java/com/moepus/serverwarashi/mixin/PersistentEntitySectionManagerAccessor.java create mode 100644 src/main/java/com/moepus/serverwarashi/mixin/ServerLevelAcessor.java diff --git a/gradle.properties b/gradle.properties index c747956..1511d5d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -29,7 +29,7 @@ mod_name=ServerWarashi # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=MIT # The mod version. See https://semver.org/ -mod_version=1.0.0 +mod_version=1.0.1 # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. # See https://maven.apache.org/guides/mini/guide-naming-conventions.html diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..31c388459f097776dcaabff76db62126b1c7d1bb GIT binary patch literal 16279 zcmajGWmH^YvIQE25IndhxI=vn3?+#hH4TK(soI`!4AUAy)PRaTTje@p!K*|TTpGScFz&z?R1`H$<(i>H4u7c!Ec zeo*YCbsV2PL&f>W_52w$h49%k5g8eAQFXVJ{Zxx8Q!VGzDT~AAvcp0H4H*qa8JdF6 z=+QJIeQzSLqA57>*%c`Tt^NGl$t&8I(*l+;NZ_Arq|L3-F5V=5Fz)A;{`gbexEvyy zFZ#~1Fk98Rtn6}eUoqkRRn(?_L<3dpG|}m;mQ@PuQ22JQagmJcQlE+cA?k7Afvanh zUHlI{JEbCVh&U*0YRwo+Mu0<5-Go=&7|#HpX1`%FX(%KMSP4{6TeXS2{QgOj|J3t? zs+1dqqb_NJ*GGJaLtj9+PuUs31So>{FG6*Xf-P)3#a~bzB438WR{)`^(%t{;f4x=)bT^q14ES(Fg!h?lu z%pR?p;9&LAZo1LOPr8v=s%~lXaKeH#_?1+N124uE(MB+(Lwq@_N)u7)H!C9FPbZkB;TDF zx%_a4g>|bC_RZ0=aTlXal&YXo0V zp7pdO4b!B!IID9)YEHjHp1t%rDeikN9u`N_6tW+aMfB`cM!h#HU`^LR7#1=RjV^#p z=9_;z2r|m+!eb~3;}mTuWn|!RJN%}NL6K?rzvB4cxe}MM^<@fRXUro}+c)Nrldc86 zw*cJS*mrQ8jq<%j=C@vvExcxCoPp4p8n@wj$e5EApVXrt3j0Z!nK@hGV`3f6U~owJ zxOlbVSsvY^AI=AH@IF4LYOU2O=S|lOkj7m}10ihOiVTWVTGXr5kf-C;`6j!2Yd2iR zBo45Dj!lIfycdw4;?=#U7q$_ug|K~HH|KysF>-m~#8;^gB4pnPn`_wd#5abFi(t1% z*Ad}=OA=N3BiEZQ20poF0msTN53WF|{LNj7;36q|dT1ckd}5b+E_d=`AVI}2w^5Fc z6#Um{TT#{oS1y++3T=k&1TbDPt8ksqTFTN_S8ZmAq8^gUbrJLjIYMT_W`EIlws8Ol zM@NLQ=kSZ?YZoCN_II!f5rkW|7jkkNibqOk%+xI$LzJ45WuTyEPsmWd!OIH2tCKbZ ze!Rb)x5S~Z(?(gly|*1~bUnnPhS(zb$GQ67`S@q;w5y;{siJ&AkHiZL38UQ{%Pxt? zg;xw?Nl>O?iCvcomOE#ZiOQFW3X$rs z=_-if#l>55l2^4&S9#~A%Ryb|hSU}kM{(0xxFwoBpRJj?LC;#kXZ@)^LYF9RoClxx zOKPn)0LSQyGMIpDGil<*r#3Ugw^dWWz?*(I0P5R~s~4IQFjgmSH;&Pxx!M zRdr8TUQX2<41ZG8^n6g|c)&v`GqJ}oC3hKGQHmwYrMNj0&@WbFwUXV}QKbo{J_vi* zQ*kbR_XKv*|2AR&Z1$w-t~s3gZV<{CHZ=t?UE)V3?;DzkyY-*E`g`ZeyF2@3q=0ezG-V zFE}~~G#e$4af2D9gV<`0zRKeA^*?lS_@YuOM9gKGx*4bNzYuu;n!cx%B#$$8%ITsL zTTu77if$1F63dUp6X!@yp9?2a=9uc{GyLPjRL{<(L6V+hM^m!c8nE)xV(jENyzg>z zSKA+pQv2V=NWp&`)ry(nWgX4xcmh2Yc?|OC{F=JoSjt0aw?>{`OktvSiclsh(#=!q zJHWf=+MDcUrx0lSavV+fUd?&gI=(rVN++HS&fZ&n&xI>_?_QykdSEfga`aij>IKz2 zLwu2zC+j?YM;u?(<{%c)Xj7WU*RWt{V)x*(_Lw_F=(fS|C&@DZAfH0pUYY=Tu(Sk8 zc`ior?ZNHqO`N$gtYzAAl-_FR+J36@g#2LE+x%3&WrS{Z!7E3F@I5Edcv<>@t4Fl| zZczUN=R?2?$0S&m(pbIl5hEZ_26@mMY|{PMd+2PiS5`^x>fwbRSrv3a%H>E_qD5=i z30ZvWaYh_1`^D{`m}G+kQ7KjYl8=!hnLM>s-d|&nW5?ykYd6nC9eJcSFM^tkl4yJ% zefDku86VDid4Y`6+P=ug=$|%3C4g|vvTQg-(&)f$V6t*Ra3*ao5U3t|oov|6xX9d2 zxA-y*^vDLt?z1mB!C-Yz^U$lx^y!cqiSOB0(i1phN#-jFPu-bju4_c-6azttEqYkoT55NkD9OdASg=;f0(91p6J;3x{_o!A*iX@U&=E=~HF z-c6nLf3`HM%O*^*W)1bqIkm0#+%S6M^8^ItnJ1Ra9GM-y7yb{nOhgt9RC=(OH&7y} znXw!9!)k?`l?!H<7%W`!Hv)M zf9?%oky*R<^Iw!EW~Yp zsh~DTe@IXq1Z49&lTub2P7^x!KA*q^a^-QYUahA5Y5Rm9U^Ap9YO-`HF-q<^y9HHn zFoF`XSt4T0sEGAe1{_o^`|x75wDmvN8%;G^M*%<8BwoyE@;se$`}}C!2Dg`F zElbI-?ixdn^=3q_=@-@cVV3(Jc0Yx0tB*Et9TLVDt#FH4t&;$8ixGLOdCC3*07oM{D$qvpXPr891Y{g&TU17@hTD_N$B{QDZH<>JP-#+x#K zIS-O+?95qe?@tb-RWAnitQ}a8HvO*MWA!|wpUjSQP>&aIOjOg_w z{{v&K2&oK>)^LTmvc@py&8jF?bJTuMM+g<%8gooPV}u6G!H&fq*RvYlh1ngJ>I@wHLNN{I4kYa z?UnloOYJ~hO)6~z!W)gCzJ|p>bw2a1a)4CCX}-Pid1{wLh&TYgupkhm>nL(pj&#Aovqp-C_pB|Mh=Qi&*GNucsvkvl7w?QFjwW+E#%$d#m z2?j`z=M16fMaIDEKlQu{mPSxVB~5m9sE(M@7O&6@d`c2~W?;;H2G|Rzr=39B92Qp> zO(f`6Yat~)rJFjx7#B9Xf9gOx=y+;W6HwxU?k|=lI|IEL^WBykDglfcyK#Ga{HTDc z>^V3nygQ9ucT{cnFL-Mjn3?%_Gh~*pnXT37@VQTmJIc@4I87xyJHMTQlrde@%y8Vz z0X5Wo71d0PI#)5NW6+u0(i_kJ@f=g+IYg7>y_qeso(ObC&*$2VB05@lqes8`baU-; z$&o`+*iAru@obhr)Wm3%s8HMcmB>f9MGh*xf4op09_!z(Ck|pWbJ_Z6jOBhhq(2A%$&Fv=xV_4rX-j(SeSNr+kp{3)GrqXu zr->F~nES*%W{MzsId$jdp#}onPTQUDMuK_3)2NqcG`~`%KOG776V*4)tRoD^_aWpJ zX`(znUtB=hbQQ#vPfZo^&1lmg#J7}p3$w&Py>pD9F86>XR4=Z0_c`(lI4vdVRNCWOCZxQm{Zc1U&5`gFMspGObtG!+1rbX#kStUs6emLP4OD6p@Xa_1s z>gsx7lcF(}K|{8@9Pgp%rgTSB_kPDb0ed6_v4cI^$bY-Q)V%)&>Rm{!7-qR}s{Wgz zD70#73))jhS)VEu<#?)a=+`rJcRjQ+&FOeLKDuul{2@9!QE1i?9Mzysr9mNH_s{9_ ze-Ph)3LF4pHN%0R0KwW@3-zoD^E$sSM}gBV3I{R(cG8AXq1Aw2|Ib+Q)7a$NhZQ;s zRrKTMzK11`;NY-u@}M3%!l8p8={b(-bH!ilg+{0(+sboFJ_*4$(^A6dkl2SU`KqJT zmIFM3BW1}i5=(BUU$6@Dj-ZV#`?1oCR%%!lJuEJVwe}tQPBQQ$4RD&Ql$9|J#K!-? zbkBfvf}dAbWdqyG3n;l%=6Uc1E(7s`x{0|cRD|p(PXX>uG<`x%nj&s{H(*yKq{*PF z{)rCE)#9yS6$P8bMmm+H#{|7cuA9LBzcTed;+IaPEy#96pBgR!0_USEDNu52gL1@^ zyCHb|<91xKJqO}`a%P)4g5zaP`yE&m9VyMn=WN|S?c_Rp&DOl-T<$G>iwDy0jvjm6kLVo)_55Kr;3z%<)o?5CaljhU=tP84 z0(vCyG|ief4Mx8WM&s*ZqogDyC4Lh|^IpZ55)lqdrF3?)q8`>mTg+MMw@ENQb;S+iT@$D>^{-M#^ zQMUh2mir&U{||L*G-z!gME7eA{&0siP$jVXyJykU4GUC|ON7XrJW){5^N2K+_XmtO zRcashDzfN4oMc=!zozWsH&FAW)o}Tg;B@oN9{0;2*$$BfP$n#BQ4~|_@a5qZRmff5 zt};0{jC*@mB`BDs&dq6zcmE3x|FOyl==nu+BXGs05>bPuM8`?P>PNMhtP`$SbreoJ z$4yrBkpmXMx@wSjx6{nHh){XfP@L`0;Jj`<0wt&0=)mVxdSFb_>4+NZ^5)9U0ij}% z=JH(4pB@v+Rzw;eO-_?yb{!VMJVguu?!P=!pyofB-+C)`?>B&FBDc?66=lOdpyS7VU zG}W41uo4RVfcy7{_l_Y=_dEuHwUO@qJ_P*nRP4Jgn*@jLjVY5!F8iqEfA*KW$?2BJ zJKE(Oy~goM&=Te&>*HZlQq>15x(m0FT%;*?9V-1QY%yr>8|ihdIx}Cx*71UOC-x#p)})*)f8}2y?sh0`=(n$ zpVu`#e2K%04`4pMDnL<_C;6@iW^MVb!vt^i@lQ^WK$xE=clGxvUbaQ(Tlmy}E(rkf zrumjpMb`0Kx{Cr^GtyP%`JC#rSsI|tczI9c+H^WGyK2%*cPJIsc2y6pgk;xo*S(;+ zT9(+z&uI3V5DC%n-v!?FH9?jLnknJel=?nnEM7#I`B4lr^9QY%LWZ7cJY9f^*M)q1 z$+K=RP{GTD&J`_NeSO^G{7zH$b3}|8MlgwlxB1Z%tj1ZHIujl6UjA&9Xfc8~0~HP8 zMFv$l4ES`(5Hwl@td&$#bBR~=yg7YTnbpSpeSM%o`ooRcAI?0`P$wDgy{A+GpioB! z_D6$W#@>4HU?ama`s(~Y&n5p9@q;+Yq%cqI_hmxrbV_WMam!>T$x2r!{7s1WtAY4A zZsdM(Q;G9=)mqzJl!J)^$_}B^gE-Te6HR&KbAVI@Dt=tC(XynRV#Fx+&mh5yicP-9 z=3SAe!(kZib5fY`V$1-0D=gyAX45;lnfNtEAMX{?T5U#q$m5xD)H130Osf%-pn4T} zx7-eLF~I1f-}mqh_7dim8EE**C&lyohmBy{D|Pgly#=FACu=`fc30{9cg}CPVLf~| zemufr$Yeo_1RfDLQ^IG*Lt<-fkyD?ut2?&Olku)X*YP!Zq`QajmUt(MSSBlw{$oq* zQxHGpE6bu7S^5ReQ17ayO)WBT?8MOQ=yv_ap>=RJEp9A0&dlX#nvqfK$8kwIBY8P< zfnv>{oUIOVZ$Gw=eqqel`x)&IyhZo-dt{FIkH(52q zd`RsOR{%(HTZ3c1LoArabKK;LusIz)bA zpy39mvgCzedjgu(d=!2>eA&ENhl-%}*}t5IpYh4s%{9u61{YMrUi#i_qmD8&<e!}EI}6UqM^tKR^#H(o$LH|vE#gLLlZCov^8+AGTe=A?NP?E8Nw znf+^zm8}4lRZw6byi|cpi)5Z8UkmPl)R#sEid%zpUwST0FUQ631A%$qtfo5SOCnx3 z5`_?%gDqN|#&Rg--2F{|exN%sR44sCGFL7%>>Iwx20QG6x9@YwE7Owa1$;yW#v4M2 z`}C&wl%Sx76?Zmg%WlQN)ncD5TK$VS1@#tS&wERtPSBXgCQ~aKB<7`8+XfvE6n<}#9a&4XuAaN@pd^6|7T46*Ai@$S!(5DW@hib z#$NDEGwRAxst&W#ymG~Ocah{gRPw#EtmAZML-(hd?}K|}hmUCDK9_@Ke$thJK8J44 z&1`{Qv6K`Q?m#;H7Y4ebucrpys`e!ZSTeOS1x5%+9`BY4AyXn>4t_SdeT7exuJ2Un zCWT@<68gpMyJe1BQiP?(xI&g_Z>^y4HaK~Ach z!yGh7zlmALM4N*xW+4Our{=ldm!3ZU!8d`1UdZA#4f%nQQCV2yKl#Q6j2u>K@Ks`0 zF5*`O3SJk_EP97y^%{Et;SxLBv?vnQs+C-Da8NhfF!8(c6AX;=j;YM2Q+Kbx z_%-!Uq~R^K;Hv3&BDSX?bT=`JQ)!*GG0}HZP*)dE z^~}UN_h@0r-L);psxThu-#TZN!=>kkf9!mTm7Xz7Dv4#6s*o+q!dX8N?eZ53{|r;{ z6wY12ny7JY+69I*ZLDjFnOrKCRa0-{V>39R@O@HKLRwhV5AMk;^AQl=pzFDsJUCLu zOrw1HVH=eEGUfWD0j4>0lR*@ca>{9~b8}8tadt#v==nW3Of|()f$a~|BS}tX(c&2= zc_D9*q7s!3OYbqHC<8V|saor9SN5LoHKf2Bylk%C1~o0=?b^pa>^kR!xjtNpe5R&} zE8jA9H;SJaC>G{@4KXtWk&A1WI=3QBMQ_7gRIHF|xPfb33C*SOv&6 zxG8r2q8jMlPd0v()J-%*|Ctk%iTR_Q)>7U_PBRUkOJ6}Zdsra@_zmbR!^I)fc-NKg z&LrND-J7T*p3XZb#&v2sC5%Veh(B@#1X={VKZ<)ip-BPwq3SxNiqOI3Mp+A>TQB&g z!8S+IE)(eL?hY6^%>*K-5<|x|t5LgY;v<`Lh5)I>)nMhQIgVYli6rs%;}eo22`L7y zR2EWfmdyQleGfi^v0n(ir9j5CBrbJxgrx2vqht@A|hS2G^A0CpW%3=G)ryvTZrIa7&f`Q6PNcAx#XbbR;g?ByI1 z-#;ad65jLSzR+xMJ%is^oe+BdX*BVm5#2B{Y2j9(ia%Xna{pwQKg?XN=?xImi$DZa z?61f9Ez5e~p;3RA@ghgp|^;Y8@G1a-DV z4TpJBAaHV6%h?leeO42>`qtVA8Z0XV^qw7hd}W|M>}vnolP+0j0uHyxhq_nDziZX{ zMv?j(qw{aWyQ9M{TF=`xXXffKX01W~w{5StriBW-8e&8@f)JrUg@# z3ETj{)3gz=C(?WzBRFa=P2=6$lvrgC=^stffP#=Un<|9BOCd&E)+682{nltmZ8M6! z4#L@1Gb&}+FGq^XdWe$-RpV@60h{F!!a6%*R&iQu4chG_f1_!VYu1*7zYLbSLB$Q( z^pMiF__7t~s<_-{N_>7E$sE7HWu(Iw*K1Hnxox6b7n>(t1zT>HdB5f1=UbE5a!a## z)rvtfdRm{IFNYmg+?sCLzMgn}#rqMDJIdJ()P!kxYzpa4rF0kqcv7`8B9Uof8kXtt ztIL}Q-3?IS#s1tRh3e$EyVG}Bqgjw{ye5FLH7UAgYME=n#;g`5d>0{Cp2A=^k{Hpj zA=51*w&1IiaM?NIpOE2Mk?oVe8dGOc^g|7|miQMHSFV|&S;cqzeP@yN{RFn<$ga2K z5+BRxZF^s4A}d#(9Dyhi^LH3~MZY2gm=f)Dyp-zFBKZ^AR zP*J_@6t?i_6kGfL3fT+${z=k1AfsKO62Mj{KN1q%Zey3)1qF2#ap7Hdo+|!@WSr)ok1pr+TY&GYCs?w z`?)xnTnjH>P-Bha2}+FfT_iY5L9z;}Gja9&&W*0QIY~@B1a9&?@rBfgKgoJr+$K88(k&M*eA20dhQd)q+y?P}SndadhSE09v zwy-LZn=^kbBHNN6ti(w3_yjXTo%)-di$ROiR3`(rtW7#op|3JC z7Hv5`x%Q1476h&5<_xV6$_Jk#gJEZf4?BuY5yh|xtejwybk`@AZai*kd1CLtH!U=j zw330KTsdd*^&zAbz{p%W-^=3_(#d+IMXRWSQ%r0*v3+l<%ZohcY~b|V197T}N~zOd zFd=tRkjnof`P(BZBKXZACx_>i@kbeq%c$7vXQ4j;~gC1;@|O z`ihxd?NrLf;GT*WJLWGgC-9Uyn#rc>h!F1QT!OgaP9;xsS87*XpB_B5@Hw7EopU5) zu@47JhDz#eXhTJQjkaK$vvAFNlpAL4g+%$6N_yIGUngV9(g8n>it_aiq?iz76%Q*b zOsvS@5)W8~>Z&F5HH72Ch88@KF*SbLx-Jkh;@(S*9JpRME8go!{mCw@z}{BgW95W# zihj$l4ZIlv7#alkbov=TW3Dadw^zuCJ*-3bG}AOlA5jxH>h3QUt9Dw#m`Cf)UcHue z^lEc7Jk}41H958BR*~U^LB}_xY`eiVzK@ZIVkSKrL4!VP&lIa?J11@@{pt51hl2ym z6uo;D&Q1j6RG^DLaw)kmHjiyntokFG1VHu?H3x0F=yjU&UXUEwsRS@`g$^Trq&QM=O z|761j&Z0pP1I0v{q+ZK$LjgUgvg6vV!uGTFKHJaLDYRsa_tVk+TG!~14;FzM+x#=Hf1ScOO1S1jB!**<6C&nIRI4L$bzzfwB zdX&Bl&_wx=GsQvX+?M{ooRj}rx^XFLNqkpm1!`Ke0!->c9k#D1$&EscHdn*m+THyw zF$|Wj2K${Y<7)DA!$QW-CJ76-6_863&y(_(p)-^CF1sl!Z+q2!C!3IqZ|TqQzuCz zAQUI3Qd<)g!h($}(UztjtjdC=d zl^5Kv57u&jlce6P0!`l!)%{IV(QUbH#*)q7HM2X*vxwyMqqcoivkm6fD6K>Vi;9OsPdC zYnFpx>68^^Qwdjx&b{LyA0o;QHEpbVdKDUG4=^uDOrS8`?SVU6>$_lLe!Kv^HA$c; z--b~qBB3Apf^Nw$V_(#@{*SeMYig2$54|^%F-VOzk-(r!XnX0Q`r7t zEd38IdfjX8!hm8O@zNAPpfa-6w0p%j@3t5`=}+Z)4=0)-5%)N{nYotm>ZzS&?R)Nq zwu43jo6ya4e_93(&#t+OSB^3ho~>7jwsa_v~KA#FuyLMQVNjF(x>7~toI?R zkjF*b!xeC^yh~h06pLWms~Q(Xj0z9=qQS zh%WQ-iJ{pB^_z&Ty-PLN>JfBaO|gOQr=MD^WktI3Q3;uG~sTVCxB;%pq$ zwQ~-$B@7PSo^E`5NTU=v2#6Phl91w`th8J#=)9nNDgerV)k@m|vQ7|y@a+oE|1$W^ z(4xkTimAjW=JFdojzqOr?PSzL3Y&8FZ~f+9I5PXQ*}l%t47+ZlAZgvv?dC`D4s)iM zzGqzIEqr8J@KYodH2zy>!r*>}SHfN3@atMwxU$dU0bl0T3cMm|eFJ1&!v87q?LoMK z?~|;0n{H&YKC~EouRMb>NUO?mYfE6$Er;Hcn(om>gOxP%p&Oe9l1G^+%Rlnc3?O|QS$O~ICc)O0mlH19fsMxAw3D;cL z<>DTe`Nc>xfq|65=gl0P+`3vwaNbnFgRT?8)!PSb)mQh-} z!S}=6zO-x?-xdfzvfm~YFGMmF-?zQQMzR|k5Tiy^ls}nM&URASv?Hg~1IHHQijdU3 zV{51?>&#*lwZ7B@CU|?CzeX_b*1djXe;cPR+L$3h=u%-{pG0G$Ui&viU}KDa?OZd3 zvK38EuvjOS4wU~SJ2VzLj8l#)*t&HveK=VmSwsMy407LlK2o3r2|9uLu>~BU>hiE1 zo2=+RzYhwL<5h6@Hb*5w^zDUPh&kl+Owfy@2Ps4uc6n){*&ceWKD>*mC>0FlR??zb z`%|w!?;?H6nB2D048-4@E{RbH*1w%5xG*=Qftf!WFlurxm+kT!+=@>px<59?70 zz~<2Baej80wn2UXU;V??h_hui%#qnw); z{%oH=TWI_nNRX&HcHdmopIaDzY2F7cydP4uC5)!5n%ara6tgsrb_iLc&^lY&7 zk#~BLuj_KindcuI1KboyXgF$t)?fYr!!746WF!^jd!JbWdkJTy-7)Ubi*5Q1-A@_I z@RO%CTpj2p<5=Y2D})e#b`rq8@b>b+ZINQeRFHnwUtYm~(Tj?txVXjHUMoJ0CTCj{ zIB>Nt(6c|kNfJBBV*6)%kY|&NKq% zh%^gWkT9r8teKk(pyfE}fZ(FGX|jGqW%HA+Xu*JpVlGSpC+CD;K@!D}5ois8Btv)e zy3^sO5z0pgqk6!{a(8soTPtcep1Pj>*LyE5(^v#^J=&c^%V)tXemFM|GAnKs zW44kxNY`#0AB82s=Kkiib(tFONTH_xYO0n-#z})79)|5XsF`ZiiEi;6FZ2x&7if>o z_}qY_@c~`?;xgXV7l|^QGdQLQ9DAav%Y_P+ueKguQS>|*?)ku$JT4Qx72r>twW+Is&2_7Os(VGFneaP($0 z){g$U9=wrhxw`5fr+YE{yS6G9jL|pqNr3%IV*c~Wn22$k(#2#495pjt$cmbPg4s5t zX!O&{OP_+-U%(HG#e20? zG=Ew@uP8;p>YYAm_&dJjlfVT*^%Ug}x#%!+>RmRGb^r~t#K^KgD>S?1DzxlanMtZ# zY~$y=h7L(r7N=veODYO8jz?Dx@&|{f?>qdZO%)URqO&`i0{u7D^1UX~aBOhhD>6hZ zAbA`1`^q)1P6TX*JWa)Vg@O7vai-N=Qk$k3?6eh8T@07kZpA@00?CJ?_+dT3c&Gdc zR)Lc`HD)a&?%guA0)x>dZHAJjQkWO_FWC13u>;sH5J^g2Ff=&>SWxBCZE4Q@mksql zXD$l<>!HIyWm$4Wp~K!U|8u;Ma+^33nUn2T9C8kvXq)PNHKF-AnNJSJjNZ$5j1>v$ z7%BaO8D^Pd&?NY4a8LE^h{#^eihTa;vAYO3C&iPl{EwpwKb+X|T@Dq$;qTm~&@W~u z${G@C&a^`wEm>g%dF7gR0Gbjj;uM9}jozcwR4-g4B?rz(m?rvl3=VNK=~tQE9zKk3 z=*}V~Tl*2^E=!FOJ3*V~g5Wu)v-Vw|zC)|>dL&5LY@@D19!}HCSJ)b?ge2*mjkDkh zkxbLFZF$KFz-@!E`Q_f@Uyv>Yd_U&-5f>C{Qs!Zyh&0YR>CDooO*~yvGvFXQAp2HF z5=O+FZmH-hC&!-R1&AR`bMmOHB-Mn7X+f3~M|YBR%!X$2$eJiBh9*{bY}6TRr?iwj zvx@S$vEM4Cx{t5c;gvFZgBbRVLS77gjoTYebFIm!Y{kaAwqg5eHH$aWlfE~(@>=_W z!_M$nk#%dLF1!n2V@pjcVLqy;3oa1O$*tkCkv<5Y{{n&{P9o=(Nu?G#ZSzhnxAr(m4d`}l}AXmHMwDhQX4I?nnMK#dlTPtduww+C(IWUX}tXo z+6utlfDIi_KPny>8}pMrzhb7^ZRX}wK5Ivk)9~dV1MfU`_B9qI&bp3UWA{{Y2tG;i zm(eX(vX=d4!7XSjqg6ESrvy chunkLoadInfoMap) { + Path logDir = Paths.get("chunk_load"); + var timestamp = LocalDateTime.now().toString().replace(":", "-").replace(".", "-"); + var fileName = "chunk_load_info_" + timestamp + ".csv"; + Path csvPath = logDir.resolve(fileName); + + try { + Files.createDirectories(logDir); + + try (BufferedWriter writer = Files.newBufferedWriter(csvPath)) { + writer.write("chunk_x,chunk_z,block_x,block_y,block_z,blockEntityCount,entityCount"); + writer.newLine(); + + for (Map.Entry entry : chunkLoadInfoMap.entrySet()) { + long chunkLong = entry.getKey(); + ChunkLoadInfo info = entry.getValue(); + + ChunkPos chunkPos = new ChunkPos(chunkLong); + BlockPos blockPos = chunkPos.getWorldPosition(); + + writer.write( + chunkPos.x + "," + + chunkPos.z + "," + + blockPos.getX() + "," + + 0 + "," + + blockPos.getZ() + "," + + info.blockEntityCount + "," + + info.entityCount + ); + writer.newLine(); + } + } + + } catch (IOException ignored) { + } + } +} diff --git a/src/main/java/com/moepus/serverwarashi/TicketOwner.java b/src/main/java/com/moepus/serverwarashi/TicketOwner.java index d6930e0..19fab3a 100644 --- a/src/main/java/com/moepus/serverwarashi/TicketOwner.java +++ b/src/main/java/com/moepus/serverwarashi/TicketOwner.java @@ -4,7 +4,9 @@ import net.minecraft.core.BlockPos; import net.minecraft.network.chat.*; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.Ticket; +import net.minecraft.server.level.TicketType; import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.block.state.BlockState; import java.lang.reflect.Field; @@ -46,6 +48,21 @@ public class TicketOwner { this.name = "Unknown entity"; } } + } else if (ticket.getType() == TicketType.PLAYER) { + owner = "player"; + final double[] mostNearDistance = {Double.MAX_VALUE}; + BlockPos ticketPos = ((ChunkPos) key).getWorldPosition(); + level.players().forEach(serverPlayer -> { + double distance = serverPlayer.blockPosition().distSqr(ticketPos); + if (distance < mostNearDistance[0]) { + mostNearDistance[0] = distance; + this.name = serverPlayer.getName().getString(); + pos = serverPlayer.blockPosition(); + } + }); + } else if (ticket.getType() == TicketType.START) { + owner = "world_start"; + this.pos = level.getSharedSpawnPos(); } else { owner = key; if (owner instanceof BlockPos blockPos) { diff --git a/src/main/java/com/moepus/serverwarashi/WarashiCommands.java b/src/main/java/com/moepus/serverwarashi/WarashiCommands.java index 79a40dc..893a298 100644 --- a/src/main/java/com/moepus/serverwarashi/WarashiCommands.java +++ b/src/main/java/com/moepus/serverwarashi/WarashiCommands.java @@ -1,6 +1,9 @@ package com.moepus.serverwarashi; import com.moepus.serverwarashi.mixin.DistanceManagerAccessor; +import com.moepus.serverwarashi.mixin.EntitySectionStorageAccessor; +import com.moepus.serverwarashi.mixin.PersistentEntitySectionManagerAccessor; +import com.moepus.serverwarashi.mixin.ServerLevelAcessor; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.IntegerArgumentType; @@ -14,15 +17,20 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.server.level.*; import net.minecraft.util.SortedArraySet; +import net.minecraft.world.entity.Entity; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.entity.EntitySection; +import net.minecraft.world.level.entity.EntitySectionStorage; +import net.minecraft.world.level.entity.PersistentEntitySectionManager; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicInteger; public class WarashiCommands { private static final java.util.function.Predicate ADMIN_PERMISSION = @@ -119,8 +127,8 @@ public class WarashiCommands { private static Ticket GetTicket(SortedArraySet> tickets, boolean currentWorking) { for (Ticket ticket : tickets) { - if (ticket.getType() == TicketType.PLAYER) continue; - if (ticket.getType() == TicketType.START) continue; + // if (ticket.getType() == TicketType.PLAYER) continue; + // if (ticket.getType() == TicketType.START) continue; int level; if (currentWorking) { @@ -129,7 +137,7 @@ public class WarashiCommands { IPauseableTicket pauseable = (IPauseableTicket) (Object) ticket; level = pauseable.serverWarashi$getLevel(); } - if (level > 32) continue; + if (level > 33) continue; return ticket; } @@ -157,25 +165,54 @@ public class WarashiCommands { ownerMap.computeIfAbsent(owner, k -> new HashSet<>()).add(chunkPos); } + PersistentEntitySectionManager entityManager = ((ServerLevelAcessor) level).getEntityManager(); + PersistentEntitySectionManagerAccessor entityAccessor = (PersistentEntitySectionManagerAccessor) entityManager; + EntitySectionStorage sectionStorage = entityAccessor.getSectionStorage(); + EntitySectionStorageAccessor sectionAccessor = (EntitySectionStorageAccessor) sectionStorage; + + HashMap chunkLoadInfoMap = new HashMap<>(); + for (var entry : ownerMap.entrySet()) { TicketOwner owner = entry.getKey(); Set chunks = entry.getValue(); message.append(owner.asComponent()); - message.append(" loads " + chunks.size() + " chunks "); + message.append(" C:" + chunks.size() + ","); + // Block Entity count int totalBlockEntities = 0; for (long chunkPos : chunks) { ChunkPos pos = new ChunkPos(chunkPos); ChunkAccess chunk = level.getChunk(pos.x, pos.z, ChunkStatus.FULL, false); if (chunk != null) { - totalBlockEntities += chunk.getBlockEntitiesPos().size(); + int chunkBlockEntities = chunk.getBlockEntitiesPos().size(); + totalBlockEntities += chunkBlockEntities; + chunkLoadInfoMap.computeIfAbsent(chunkPos, k -> new ChunkLoadInfo()).blockEntityCount = chunkBlockEntities; } } - message.append("with " + totalBlockEntities + " block entities\n"); + message.append(" BE: " + totalBlockEntities + ","); + + // Entity count + int totalEntities = 0; + for (long chunkPos : chunks) { + ChunkPos pos = new ChunkPos(chunkPos); + AtomicInteger chunkEntities = new AtomicInteger(); + sectionAccessor.invokeGetChunkSections(pos.x, pos.z).forEach(sectionIndex -> { + EntitySection section = sectionStorage.getSection(sectionIndex); + if (section == null) + return; + chunkEntities.addAndGet(section.size()); + }); + totalEntities += chunkEntities.get(); + chunkLoadInfoMap.computeIfAbsent(chunkPos, k -> new ChunkLoadInfo()).entityCount = chunkEntities.get(); + } + message.append(" E: " + totalEntities + ".\n"); } if (ownerMap.isEmpty()) { message.append("No tickets found\n"); } + if (!chunkLoadInfoMap.isEmpty()) { + ChunkLoadInfo.dumpToCsv(chunkLoadInfoMap); + } return message; }, true) ; diff --git a/src/main/java/com/moepus/serverwarashi/mixin/EntitySectionStorageAccessor.java b/src/main/java/com/moepus/serverwarashi/mixin/EntitySectionStorageAccessor.java new file mode 100644 index 0000000..e2d1c30 --- /dev/null +++ b/src/main/java/com/moepus/serverwarashi/mixin/EntitySectionStorageAccessor.java @@ -0,0 +1,12 @@ +package com.moepus.serverwarashi.mixin; + +import it.unimi.dsi.fastutil.longs.LongSortedSet; +import net.minecraft.world.level.entity.EntitySectionStorage; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(value = EntitySectionStorage.class, remap = false) +public interface EntitySectionStorageAccessor { + @Invoker + LongSortedSet invokeGetChunkSections(int x, int z); +} diff --git a/src/main/java/com/moepus/serverwarashi/mixin/PersistentEntitySectionManagerAccessor.java b/src/main/java/com/moepus/serverwarashi/mixin/PersistentEntitySectionManagerAccessor.java new file mode 100644 index 0000000..aad8c21 --- /dev/null +++ b/src/main/java/com/moepus/serverwarashi/mixin/PersistentEntitySectionManagerAccessor.java @@ -0,0 +1,12 @@ +package com.moepus.serverwarashi.mixin; + +import net.minecraft.world.level.entity.EntitySectionStorage; +import net.minecraft.world.level.entity.PersistentEntitySectionManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(value = PersistentEntitySectionManager.class, remap = false) +public interface PersistentEntitySectionManagerAccessor { + @Accessor + EntitySectionStorage getSectionStorage(); +} diff --git a/src/main/java/com/moepus/serverwarashi/mixin/ServerLevelAcessor.java b/src/main/java/com/moepus/serverwarashi/mixin/ServerLevelAcessor.java new file mode 100644 index 0000000..bff1cb7 --- /dev/null +++ b/src/main/java/com/moepus/serverwarashi/mixin/ServerLevelAcessor.java @@ -0,0 +1,13 @@ +package com.moepus.serverwarashi.mixin; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.entity.PersistentEntitySectionManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(value = ServerLevel.class, remap = false) +public interface ServerLevelAcessor { + @Accessor + PersistentEntitySectionManager getEntityManager(); +} diff --git a/src/main/resources/serverwarashi.mixins.json b/src/main/resources/serverwarashi.mixins.json index 35928f6..8a05865 100644 --- a/src/main/resources/serverwarashi.mixins.json +++ b/src/main/resources/serverwarashi.mixins.json @@ -5,6 +5,9 @@ "compatibilityLevel": "JAVA_21", "mixins": [ "DistanceManagerAccessor", + "EntitySectionStorageAccessor", + "PersistentEntitySectionManagerAccessor", + "ServerLevelAcessor", "TicketMixin" ], "client": [